[PATCH 1/9] Gccgo port to s390[x] is a fix for BZ 60406. When building with this patch on ppc64 LE, the failing testcase from the BZ is fixed and there are no new failures; however when building with this patch on ppc64 BE there are over 20 new failures in the go and libgo testsuites.

I modified the patch for statements.cc and rebuilt and that eliminates the regressions and fixes the original problem it was intended to fix for both ppc64 BE & LE. The ABIs are different between BE & LE, so that make_func_code_reference on ppc64 BE is not returning the function's code address but the function pointer from the .opd. The first 8 bytes of the entry in the .opd is the function's code address. Here is the change to statements.cc that made it work:

-- statements.cc       (revision 215466)
+++ statements.cc       (working copy)
@@ -2355,25 +2355,25 @@
   gogo->start_block(location);

   // For a defer statement, start with a call to
-  // __go_set_defer_retaddr.  */
-  Label* retaddr_label = NULL;
+  // __go_set_defering_fn.  */
   if (may_call_recover)
     {
- retaddr_label = gogo->add_label_reference("retaddr", location, false); - Expression* arg = Expression::make_label_addr(retaddr_label, location);
-      Expression* call = Runtime::make_call(Runtime::SET_DEFER_RETADDR,
-                                           location, 1, arg);
-
-      // This is a hack to prevent the middle-end from deleting the
-      // label.
-      gogo->start_block(location);
- gogo->add_statement(Statement::make_goto_statement(retaddr_label,
-                                                        location));
-      Block* then_block = gogo->finish_block(location);
-      then_block->determine_types();
-
-      Statement* s = Statement::make_if_statement(call, then_block, NULL,
-                                                 location);
+#if defined(__powerpc64__) && _CALL_ELF != 2
+      Expression* pfn =
+        Expression::make_func_code_reference(function, location);
+      Type* pfntype =
+          Type::make_pointer_type(
+              Type::make_pointer_type(Type::make_void_type()));
+ Expression* fn = Expression::make_unsafe_cast(pfntype, pfn, location);
+      Expression* fn_code_addr = Expression::make_unary(OPERATOR_MULT, fn,
+                                                        location);
+#else
+      Expression* fn_code_addr =
+        Expression::make_func_code_reference(function, location);
+#endif
+      Expression* call = Runtime::make_call(Runtime::SET_DEFERING_FN,
+                                            location, 1, fn_code_addr);
+      Statement* s = Statement::make_statement(call, true);
       s->determine_types();
       gogo->add_statement(s);
     }
@@ -2477,12 +2477,8 @@

   gogo->add_statement(call_statement);

-  // If this is a defer statement, the label comes immediately after
-  // the call.
   if (may_call_recover)
     {
-      gogo->add_label_definition("retaddr", location);
-
       Expression_list* vals = new Expression_list();
       vals->push_back(Expression::make_boolean(false, location));
gogo->add_statement(Statement::make_return_statement(vals, location));

Reply via email to