aboutsummaryrefslogtreecommitdiff
path: root/gcc/go
diff options
context:
space:
mode:
authorChris Manghane <cmang@google.com>2013-12-16 19:58:50 +0000
committerIan Lance Taylor <iant@google.com>2013-12-16 19:58:50 +0000
commit8a140f064f2a6ec02b467e5c0ff79b71734c522e (patch)
treed9380cfc26a9af9a9f0f214d08c54d1da389bb26 /gcc/go
parentf435a0409ecd1a1b70493426148c8838fa0a9eb6 (diff)
compiler: Use backend interface for struct field expressions.
* go-gcc.cc (Gcc_backend::struct_field_expression): New function. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@206029 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/go')
-rw-r--r--gcc/go/ChangeLog4
-rw-r--r--gcc/go/go-gcc.cc36
-rw-r--r--gcc/go/gofrontend/backend.h4
-rw-r--r--gcc/go/gofrontend/expressions.cc28
4 files changed, 50 insertions, 22 deletions
diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog
index db0212cd37d..f6e6599bda3 100644
--- a/gcc/go/ChangeLog
+++ b/gcc/go/ChangeLog
@@ -1,3 +1,7 @@
+2013-12-16 Chris Manghane <cmang@google.com>
+
+ * go-gcc.cc (Gcc_backend::struct_field_expression): New function.
+
2013-12-11 Ian Lance Taylor <iant@google.com>
* go-lang.c (go_langhook_post_options): Disable sibling calls by
diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc
index 939be20c349..db8fd5e3355 100644
--- a/gcc/go/go-gcc.cc
+++ b/gcc/go/go-gcc.cc
@@ -243,6 +243,9 @@ class Gcc_backend : public Backend
Bexpression*
address_expression(Bexpression*, Location);
+ Bexpression*
+ struct_field_expression(Bexpression*, size_t, Location);
+
// Statements.
Bstatement*
@@ -998,6 +1001,39 @@ Gcc_backend::address_expression(Bexpression* bexpr, Location location)
return this->make_expression(ret);
}
+// Return an expression for the field at INDEX in BSTRUCT.
+
+Bexpression*
+Gcc_backend::struct_field_expression(Bexpression* bstruct, size_t index,
+ Location location)
+{
+ tree struct_tree = bstruct->get_tree();
+ if (struct_tree == error_mark_node
+ || TREE_TYPE(struct_tree) == error_mark_node)
+ return this->error_expression();
+ gcc_assert(TREE_CODE(TREE_TYPE(struct_tree)) == RECORD_TYPE);
+ tree field = TYPE_FIELDS(TREE_TYPE(struct_tree));
+ if (field == NULL_TREE)
+ {
+ // This can happen for a type which refers to itself indirectly
+ // and then turns out to be erroneous.
+ return this->error_expression();
+ }
+ for (unsigned int i = index; i > 0; --i)
+ {
+ field = DECL_CHAIN(field);
+ gcc_assert(field != NULL_TREE);
+ }
+ if (TREE_TYPE(field) == error_mark_node)
+ return this->error_expression();
+ tree ret = fold_build3_loc(location.gcc_location(), COMPONENT_REF,
+ TREE_TYPE(field), struct_tree, field,
+ NULL_TREE);
+ if (TREE_CONSTANT(struct_tree))
+ TREE_CONSTANT(ret) = 1;
+ return tree_to_expr(ret);
+}
+
// An expression as a statement.
Bstatement*
diff --git a/gcc/go/gofrontend/backend.h b/gcc/go/gofrontend/backend.h
index 8344da40120..55805941da6 100644
--- a/gcc/go/gofrontend/backend.h
+++ b/gcc/go/gofrontend/backend.h
@@ -280,6 +280,10 @@ class Backend
virtual Bexpression*
address_expression(Bexpression*, Location) = 0;
+ // Return an expression for the field at INDEX in BSTRUCT.
+ virtual Bexpression*
+ struct_field_expression(Bexpression* bstruct, size_t index, Location) = 0;
+
// Statements.
// Create an error statement. This is used for cases which should
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 35bcdbb5145..81d18caae7a 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -11539,28 +11539,12 @@ Field_reference_expression::do_check_types(Gogo*)
tree
Field_reference_expression::do_get_tree(Translate_context* context)
{
- tree struct_tree = this->expr_->get_tree(context);
- if (struct_tree == error_mark_node
- || TREE_TYPE(struct_tree) == error_mark_node)
- return error_mark_node;
- go_assert(TREE_CODE(TREE_TYPE(struct_tree)) == RECORD_TYPE);
- tree field = TYPE_FIELDS(TREE_TYPE(struct_tree));
- if (field == NULL_TREE)
- {
- // This can happen for a type which refers to itself indirectly
- // and then turns out to be erroneous.
- go_assert(saw_errors());
- return error_mark_node;
- }
- for (unsigned int i = this->field_index_; i > 0; --i)
- {
- field = DECL_CHAIN(field);
- go_assert(field != NULL_TREE);
- }
- if (TREE_TYPE(field) == error_mark_node)
- return error_mark_node;
- return build3(COMPONENT_REF, TREE_TYPE(field), struct_tree, field,
- NULL_TREE);
+ Bexpression* bstruct = tree_to_expr(this->expr_->get_tree(context));
+ Bexpression* ret =
+ context->gogo()->backend()->struct_field_expression(bstruct,
+ this->field_index_,
+ this->location());
+ return expr_to_tree(ret);
}
// Dump ast representation for a field reference expression.