[m-rev.] for review: fix bug #196: binary compatiblity checks in C grade don't work

Julien Fischer jfischer at opturion.com
Thu Jul 7 22:34:36 AEST 2016


For review by anyone.

I haven't had a chance to look at whether MSVC is affected by bug #196, 
but will do so shortly.  If anyone is using Mercury with a C compiler that
is not GCC, clang, or MSVC could they please take a look what whether
MR_grade is being optimised away as well.

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

Fix bug #196: binary compatibility checks in C grades don't work.

These have been broken since 2011 because GCC and clang (at least) began
optimising away the MR_grade variable we emit at the end of each generated
.c file.  For these C compilers attach an attribute that prevents them from
doing this; for other C compilers declare MR_grade to be volatile (although
that didn't prevent GCC or clang deleting MR_grade).

runtime/mercury_std.h:
     Add a new macro MR_CONSIDER_USED, that expands to an attribute that
     tells the C compiler not to optimise a way a static variable even
     if it is unreferenced.

util/mkinit.c:
compiler/mlds_to_c.m:
compiler/llds_outfile.m:
     Use the new macro in the definition of MR_grade.

Julien.

diff --git a/compiler/llds_out_file.m b/compiler/llds_out_file.m
index f437ce4..9b919ce 100644
--- a/compiler/llds_out_file.m
+++ b/compiler/llds_out_file.m
@@ -616,7 +616,7 @@ output_c_module_init_list(Info, ModuleName, AnnotatedModules, RttiDatas,
          "/* ensure everything is compiled with the same grade */\n",
          !IO),
      io.write_string(
-        "static const void *const MR_grade = &MR_GRADE_VAR;\n", !IO).
+        "static const void *const MR_CONSIDER_USED MR_grade = &MR_GRADE_VAR;\n", !IO).

  :- pred module_defines_label_with_layout(llds_out_info::in,
      annotated_c_module::in) is semidet.
diff --git a/compiler/mlds_to_c.m b/compiler/mlds_to_c.m
index eeb570c..bea8b28 100644
--- a/compiler/mlds_to_c.m
+++ b/compiler/mlds_to_c.m
@@ -679,7 +679,7 @@ mlds_output_grade_var(!IO) :-
          "/* ensure everything is compiled with the same grade */\n",
          !IO),
      io.write_string(
-        "static const void *const MR_grade = &MR_GRADE_VAR;\n",
+        "static const void *const MR_CONSIDER_USED MR_grade = &MR_GRADE_VAR;\n",
          !IO).

      % Get the foreign code for C.
diff --git a/runtime/mercury_std.h b/runtime/mercury_std.h
index d3f761a..b3baecb 100644
--- a/runtime/mercury_std.h
+++ b/runtime/mercury_std.h
@@ -220,6 +220,21 @@ typedef	char		MR_small_bool;
  /*---------------------------------------------------------------------------*/

  /*
+** A macro for declaring that a variable with static storage class must be
+** considered used even if it is not referenced.  We use this to ensure that
+** the MR_grade variable emitted at the end of every generated .c file is
+** not optimised away.
+*/
+
+#if defined(MR_GNUC) || defined(MR_CLANG)
+   #define MR_CONSIDER_USED __attribute__((used))
+#else
+   #define MR_CONSIDER_USED volatile
+#endif
+
+/*---------------------------------------------------------------------------*/
+
+/*
  ** MR_CALL:
  ** A macro for specifying the calling convention to use
  ** for C functions generated by the MLDS back-end
diff --git a/util/mkinit.c b/util/mkinit.c
index 0e15a60..8be079c 100644
--- a/util/mkinit.c
+++ b/util/mkinit.c
@@ -621,7 +621,7 @@ static const char mercury_main_func[] =

  static const char mercury_grade_var[] =
      "/* ensure that everything gets compiled in the same grade */\n"
-    "static const void *const MR_grade = &MR_GRADE_VAR;\n"
+    "static const void *const MR_CONSIDER_USED MR_grade = &MR_GRADE_VAR;\n"
      "\n"
      ;



More information about the reviews mailing list