[m-rev.] for review: workaround bug #307

Julien Fischer jfischer at opturion.com
Thu Jan 9 03:15:42 AEDT 2014


For review by anyone.

Branches: master, 14.01
(This diff could also be applied to the 13.05 branch if required.)

---------------------

Add a workaround for bug #307.

We encounter internal errors in GCC 4.8.2 on i686 Linux when compiling
runtime/mercury_ho_call.c in grades that use global registers when -fpic is
enabled.  This change adds a test to configure to check whether GCC 4.8.X is
broken in this way and, if so, forces the use of `none' as the LLDS base grade.

I've looked for combination of GCC options that avoid the above problem, but
the only one that seems to have any affect is -fomit-frame-pointer, which is
one that we are required to disable on i686 anyway.  (Compiling at -O0 also
avoids the problem -- I'll look into compiling just runtime/mercury_ho_call.c
with that separately.)

configure.ac:
 	As above.

Julien.

diff --git a/configure.ac b/configure.ac
index 07c5a18..8bdc7af 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2760,6 +2760,84 @@ CC="$save_CC"

  #-----------------------------------------------------------------------------#

+# Compiling runtime/mercury_ho_call.c with -fpic enabled causes an internal
+# error in GCC 4.8.2 on i*86 Linux when global registers are enabled.
+# The following test checks if GCC is broken in this way -- if it is then
+# we disable the use of all GCC extensions.  Doing so is the best means of
+# ensuring that the installation succeeds.
+
+case "$host" in i*86-*linux*)
+
+    case "$C_COMPILER_TYPE" in
+        gcc_4_8*)
+            AC_MSG_CHECKING([whether we can use global registers with -fpic])
+
+cat > conftest.c << EOF
+
+    typedef struct {
+        void *MR_closure_code;
+        unsigned int MR_closure_num_hidden_args_rf;
+        unsigned int MR_closure_hidden_args_0[0];
+    } MR_Closure;
+
+    typedef struct MR_mercury_engine_struct {
+        unsigned int MR_eng_fake_reg[1044];
+    } MercuryEngine;
+
+    register unsigned int MR_mr0 __asm__("esi");
+    register unsigned int MR_mr1 __asm__("edi");
+
+    extern unsigned int MR_real_r_reg_map[32];
+    extern MercuryEngine MR_engine_base;
+
+    void *mercury__do_call_closure_compact(void);
+
+    void* mercury__do_call_closure_compact(void)
+    {
+        MR_Closure *closure;
+        int num_hidden_r_args;
+
+        int i;
+
+        closure = (MR_Closure *) MR_engine_base.MR_eng_fake_reg[2];
+        num_hidden_r_args = closure->MR_closure_num_hidden_args_rf & 0xffff;
+
+        for (i = 1; i <= num_hidden_r_args; i++) {
+            if (i > 32) { 
+                MR_engine_base.MR_eng_fake_reg[i + 19] =
+                    closure->MR_closure_hidden_args_0[i - 1];
+ 
+            } else { 
+                MR_engine_base.MR_eng_fake_reg[MR_real_r_reg_map[i - 1]] =
+                    closure->MR_closure_hidden_args_0[i - 1]; 
+            }
+        }
+        return closure->MR_closure_code;
+    }
+
+EOF
+            if $CC -c -O1 -fno-omit-frame-pointer -fpic conftest.c \
+                >&AC_FD_CC 2>&1
+            then
+                AC_MSG_RESULT([yes])
+            else
+                AC_MSG_RESULT([no])
+                # If the above test failed the force the use of `none' as the
+                # LLDS base grade.
+                mercury_cv_asm_labels=no
+                mercury_cv_gcc_labels=no
+                mercury_cv_gcc_model_fast=no
+                mercury_cv_gcc_model_reg=no
+                mercury_cv_gcc_model_labels=no
+            fi
+            rm -f conftest*
+            ;;
+        esac
+        ;;
+esac
+
+#-----------------------------------------------------------------------------#
+
  AC_MSG_CHECKING(whether we can support profiling on this system)
  AC_CACHE_VAL(mercury_cv_profiling,
  AC_TRY_CPP([




More information about the reviews mailing list