summaryrefslogtreecommitdiff
path: root/gcc/go
diff options
context:
space:
mode:
authorbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2012-03-15 09:35:56 +0000
committerbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2012-03-15 09:35:56 +0000
commite8844fc36936140eb1c9f659a16b401980733b49 (patch)
tree604287ecd222a7298e95b6799dafc8e1b6467250 /gcc/go
parent5ce2a6ec8443c9fcf3c4f96383246efa8f5b3d6a (diff)
downloadgcc-e8844fc36936140eb1c9f659a16b401980733b49.tar.gz
2012-03-15 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk rev 185416 using svnmerge git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@185423 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/go')
-rw-r--r--gcc/go/ChangeLog16
-rw-r--r--gcc/go/config-lang.in2
-rw-r--r--gcc/go/go-c.h2
-rw-r--r--gcc/go/go-gcc.cc109
-rw-r--r--gcc/go/gofrontend/expressions.cc15
-rw-r--r--gcc/go/gofrontend/gogo-tree.cc4
-rw-r--r--gcc/go/gofrontend/gogo.cc5
7 files changed, 139 insertions, 14 deletions
diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog
index 8b8e90c4b68..f779e9b89cf 100644
--- a/gcc/go/ChangeLog
+++ b/gcc/go/ChangeLog
@@ -1,3 +1,19 @@
+2012-03-09 Ian Lance Taylor <iant@google.com>
+
+ * go-gcc.cc (Gcc_backend::assignment_statement): Convert the rhs
+ to the lhs type if necessary.
+
+2012-03-08 Ian Lance Taylor <iant@google.com>
+
+ * go-gcc.cc (Gcc_backend::init_statement): Don't initialize a
+ zero-sized variable.
+ (go_non_zero_struct): New global variable.
+ (Gcc_backend::non_zero_size_type): New function.
+ (Gcc_backend::global_variable): Don't build an assignment for a
+ zero-sized value.
+ * go-c.h (go_non_zero_struct): Declare.
+ * config-lang.in (gtfiles): Add go-c.h.
+
2012-02-29 Ian Lance Taylor <iant@google.com>
* go-gcc.cc (class Gcc_tree): Add set_tree method.
diff --git a/gcc/go/config-lang.in b/gcc/go/config-lang.in
index 4b5886eb758..586e070e7d1 100644
--- a/gcc/go/config-lang.in
+++ b/gcc/go/config-lang.in
@@ -34,7 +34,7 @@ target_libs="target-libgo target-libffi"
# compiler during stage 1.
lang_requires_boot_languages=c++
-gtfiles="\$(srcdir)/go/go-lang.c"
+gtfiles="\$(srcdir)/go/go-lang.c \$(srcdir)/go/go-c.h"
# Do not build by default.
build_by_default="no"
diff --git a/gcc/go/go-c.h b/gcc/go/go-c.h
index 0bfed85322a..e123d52d8d1 100644
--- a/gcc/go/go-c.h
+++ b/gcc/go/go-c.h
@@ -69,6 +69,8 @@ extern void go_write_export_data (const char *, unsigned int);
extern const char *go_read_export_data (int, off_t, char **, size_t *, int *);
+extern GTY(()) tree go_non_zero_struct;
+
#if defined(__cplusplus) && !defined(ENABLE_BUILD_WITH_CXX)
} /* End extern "C". */
#endif
diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc
index a19bb894a99..96c171835c4 100644
--- a/gcc/go/go-gcc.cc
+++ b/gcc/go/go-gcc.cc
@@ -338,6 +338,9 @@ class Gcc_backend : public Backend
Btype*
fill_in_array(Btype*, Btype*, Bexpression*);
+
+ tree
+ non_zero_size_type(tree);
};
// A helper function.
@@ -870,9 +873,27 @@ Gcc_backend::init_statement(Bvariable* var, Bexpression* init)
if (var_tree == error_mark_node || init_tree == error_mark_node)
return this->error_statement();
gcc_assert(TREE_CODE(var_tree) == VAR_DECL);
- DECL_INITIAL(var_tree) = init_tree;
- return this->make_statement(build1_loc(DECL_SOURCE_LOCATION(var_tree),
- DECL_EXPR, void_type_node, var_tree));
+
+ // To avoid problems with GNU ld, we don't make zero-sized
+ // externally visible variables. That might lead us to doing an
+ // initialization of a zero-sized expression to a non-zero sized
+ // variable, or vice-versa. Avoid crashes by omitting the
+ // initializer. Such initializations don't mean anything anyhow.
+ if (int_size_in_bytes(TREE_TYPE(var_tree)) != 0
+ && init_tree != NULL_TREE
+ && int_size_in_bytes(TREE_TYPE(init_tree)) != 0)
+ {
+ DECL_INITIAL(var_tree) = init_tree;
+ init_tree = NULL_TREE;
+ }
+
+ tree ret = build1_loc(DECL_SOURCE_LOCATION(var_tree), DECL_EXPR,
+ void_type_node, var_tree);
+ if (init_tree != NULL_TREE)
+ ret = build2_loc(DECL_SOURCE_LOCATION(var_tree), COMPOUND_EXPR,
+ void_type_node, init_tree, ret);
+
+ return this->make_statement(ret);
}
// Assignment.
@@ -885,6 +906,42 @@ Gcc_backend::assignment_statement(Bexpression* lhs, Bexpression* rhs,
tree rhs_tree = rhs->get_tree();
if (lhs_tree == error_mark_node || rhs_tree == error_mark_node)
return this->error_statement();
+
+ // To avoid problems with GNU ld, we don't make zero-sized
+ // externally visible variables. That might lead us to doing an
+ // assignment of a zero-sized expression to a non-zero sized
+ // expression; avoid crashes here by avoiding assignments of
+ // zero-sized expressions. Such assignments don't really mean
+ // anything anyhow.
+ if (int_size_in_bytes(TREE_TYPE(lhs_tree)) == 0
+ || int_size_in_bytes(TREE_TYPE(rhs_tree)) == 0)
+ return this->compound_statement(this->expression_statement(lhs),
+ this->expression_statement(rhs));
+
+ // Sometimes the same unnamed Go type can be created multiple times
+ // and thus have multiple tree representations. Make sure this does
+ // not confuse the middle-end.
+ if (TREE_TYPE(lhs_tree) != TREE_TYPE(rhs_tree))
+ {
+ tree lhs_type_tree = TREE_TYPE(lhs_tree);
+ gcc_assert(TREE_CODE(lhs_type_tree) == TREE_CODE(TREE_TYPE(rhs_tree)));
+ if (POINTER_TYPE_P(lhs_type_tree)
+ || INTEGRAL_TYPE_P(lhs_type_tree)
+ || SCALAR_FLOAT_TYPE_P(lhs_type_tree)
+ || COMPLEX_FLOAT_TYPE_P(lhs_type_tree))
+ rhs_tree = fold_convert_loc(location.gcc_location(), lhs_type_tree,
+ rhs_tree);
+ else if (TREE_CODE(lhs_type_tree) == RECORD_TYPE
+ || TREE_CODE(lhs_type_tree) == ARRAY_TYPE)
+ {
+ gcc_assert(int_size_in_bytes(lhs_type_tree)
+ == int_size_in_bytes(TREE_TYPE(rhs_tree)));
+ rhs_tree = fold_build1_loc(location.gcc_location(),
+ VIEW_CONVERT_EXPR,
+ lhs_type_tree, rhs_tree);
+ }
+ }
+
return this->make_statement(fold_build2_loc(location.gcc_location(),
MODIFY_EXPR,
void_type_node,
@@ -1178,6 +1235,48 @@ Gcc_backend::block_statement(Bblock* bblock)
return this->make_statement(bind_tree);
}
+// This is not static because we declare it with GTY(()) in go-c.h.
+tree go_non_zero_struct;
+
+// Return a type corresponding to TYPE with non-zero size.
+
+tree
+Gcc_backend::non_zero_size_type(tree type)
+{
+ if (int_size_in_bytes(type) != 0)
+ return type;
+
+ switch (TREE_CODE(type))
+ {
+ case RECORD_TYPE:
+ {
+ if (go_non_zero_struct == NULL_TREE)
+ {
+ type = make_node(RECORD_TYPE);
+ tree field = build_decl(UNKNOWN_LOCATION, FIELD_DECL,
+ get_identifier("dummy"),
+ boolean_type_node);
+ DECL_CONTEXT(field) = type;
+ TYPE_FIELDS(type) = field;
+ layout_type(type);
+ go_non_zero_struct = type;
+ }
+ return go_non_zero_struct;
+ }
+
+ case ARRAY_TYPE:
+ {
+ tree element_type = non_zero_size_type(TREE_TYPE(type));
+ return build_array_type_nelts(element_type, 1);
+ }
+
+ default:
+ gcc_unreachable();
+ }
+
+ gcc_unreachable();
+}
+
// Make a global variable.
Bvariable*
@@ -1193,6 +1292,10 @@ Gcc_backend::global_variable(const std::string& package_name,
if (type_tree == error_mark_node)
return this->error_variable();
+ // The GNU linker does not like dynamic variables with zero size.
+ if ((is_external || !is_hidden) && int_size_in_bytes(type_tree) == 0)
+ type_tree = this->non_zero_size_type(type_tree);
+
std::string var_name(package_name);
var_name.push_back('.');
var_name.append(name);
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 134b5ae2aae..90cf6f32dab 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -205,9 +205,6 @@ Expression::convert_for_assignment(Translate_context* context, Type* lhs_type,
Type* rhs_type, tree rhs_tree,
Location location)
{
- if (lhs_type == rhs_type)
- return rhs_tree;
-
if (lhs_type->is_error() || rhs_type->is_error())
return error_mark_node;
@@ -220,7 +217,7 @@ Expression::convert_for_assignment(Translate_context* context, Type* lhs_type,
if (lhs_type_tree == error_mark_node)
return error_mark_node;
- if (lhs_type->interface_type() != NULL)
+ if (lhs_type != rhs_type && lhs_type->interface_type() != NULL)
{
if (rhs_type->interface_type() == NULL)
return Expression::convert_type_to_interface(context, lhs_type,
@@ -231,7 +228,7 @@ Expression::convert_for_assignment(Translate_context* context, Type* lhs_type,
rhs_type, rhs_tree,
false, location);
}
- else if (rhs_type->interface_type() != NULL)
+ else if (lhs_type != rhs_type && rhs_type->interface_type() != NULL)
return Expression::convert_interface_to_type(context, lhs_type, rhs_type,
rhs_tree, location);
else if (lhs_type->is_slice_type() && rhs_type->is_nil_type())
@@ -289,10 +286,16 @@ Expression::convert_for_assignment(Translate_context* context, Type* lhs_type,
|| (TREE_CODE(lhs_type_tree) == ARRAY_TYPE
&& TREE_CODE(TREE_TYPE(rhs_tree)) == ARRAY_TYPE))
{
+ // Avoid confusion from zero sized variables which may be
+ // represented as non-zero-sized.
+ if (int_size_in_bytes(lhs_type_tree) == 0
+ || int_size_in_bytes(TREE_TYPE(rhs_tree)) == 0)
+ return rhs_tree;
+
// This conversion must be permitted by Go, or we wouldn't have
// gotten here.
go_assert(int_size_in_bytes(lhs_type_tree)
- == int_size_in_bytes(TREE_TYPE(rhs_tree)));
+ == int_size_in_bytes(TREE_TYPE(rhs_tree)));
return fold_build1_loc(location.gcc_location(), VIEW_CONVERT_EXPR,
lhs_type_tree, rhs_tree);
}
diff --git a/gcc/go/gofrontend/gogo-tree.cc b/gcc/go/gofrontend/gogo-tree.cc
index 603b97ec0c1..fa229320c96 100644
--- a/gcc/go/gofrontend/gogo-tree.cc
+++ b/gcc/go/gofrontend/gogo-tree.cc
@@ -843,7 +843,9 @@ Gogo::write_globals()
this->backend()->global_variable_set_init(var,
tree_to_expr(init));
}
- else if (is_sink)
+ else if (is_sink
+ || int_size_in_bytes(TREE_TYPE(init)) == 0
+ || int_size_in_bytes(TREE_TYPE(vec[i])) == 0)
var_init_tree = init;
else
var_init_tree = fold_build2_loc(no->location().gcc_location(),
diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc
index ca57aea26ee..5fe5aead9c0 100644
--- a/gcc/go/gofrontend/gogo.cc
+++ b/gcc/go/gofrontend/gogo.cc
@@ -628,7 +628,7 @@ Gogo::start_function(const std::string& name, Function_type* type,
Variable* this_param = new Variable(receiver->type(), NULL, false,
true, true, location);
std::string rname = receiver->name();
- if (rname.empty())
+ if (rname.empty() || Gogo::is_sink_name(rname))
{
// We need to give receivers a name since they wind up in
// DECL_ARGUMENTS. FIXME.
@@ -638,8 +638,7 @@ Gogo::start_function(const std::string& name, Function_type* type,
++count;
rname = buf;
}
- if (!Gogo::is_sink_name(rname))
- block->bindings()->add_variable(rname, NULL, this_param);
+ block->bindings()->add_variable(rname, NULL, this_param);
}
const Typed_identifier_list* parameters = type->parameters();