From 7a408d9bedfd0082e1430f057fc8bd979b5abee8 Mon Sep 17 00:00:00 2001
From: Kostyantyn Vorobyov <kostyantyn.vorobyov@cea.fr>
Date: Wed, 3 Feb 2016 18:04:33 +0100
Subject: [PATCH] Brought forward changes from the segment-model remote:     -
 structural changes to e-acsl wrapper script     - --memory-model option in
 the e-acsl wrapper script that allows         switching between different
 memory models     - added script to facilitate runs of e-acsl during    
 testing (scripts/testrun.sh)

---
 src/plugins/e-acsl/scripts/e-acsl-gcc.sh | 168 +++++++++++++++++------
 src/plugins/e-acsl/scripts/testrun.sh    |  97 +++++++++++++
 2 files changed, 226 insertions(+), 39 deletions(-)
 create mode 100755 src/plugins/e-acsl/scripts/testrun.sh

diff --git a/src/plugins/e-acsl/scripts/e-acsl-gcc.sh b/src/plugins/e-acsl/scripts/e-acsl-gcc.sh
index dae2bc058f4..24ef7b8816d 100755
--- a/src/plugins/e-acsl/scripts/e-acsl-gcc.sh
+++ b/src/plugins/e-acsl/scripts/e-acsl-gcc.sh
@@ -46,18 +46,25 @@ check_tool() {
 
 # Getopt options
 LONGOPTIONS="help,compile,compile-only,print,debug:,ocode:,oexec:,verbose:, \
-  frama-c-only,extra-cpp-args,rtl,frama-c-stdlib,full-mmodel,gmp,quiet,logfile:,
-  ld-flags:,cpp-flags:,frama-c-extra:"
-SHORTOPTIONS="h,c,C,p,d:,o:,O:,v:,f,E:,R,L,M,l:,e:,g,q,s:,F:"
+  frama-c-only,extra-cpp-args:,frama-c-stdlib,full-mmodel,gmp,quiet,logfile:,
+  ld-flags:,cpp-flags:,frama-c-extra:,memory-model:,production,no-stdlib,
+  debug-log:"
+SHORTOPTIONS="h,c,C,p,d:,o:,O:,v:,f,E:,L,M,l:,e:,g,q,s:,F:,m:,P,N,D:"
 # Prefix for an error message due to wrong arguments
 ERROR="ERROR parsing arguments:"
 
+# Frama-C
+FRAMAC="`check_tool 'frama-c'`"
+FRAMAC_CONGIG="`check_tool 'frama-c-config'`"
+FRAMAC_FLAGS=""
+FRAMA_C_SHARE="`$FRAMAC_CONGIG -print-share-path`"
+
 # Architecture-dependent flags. Since by default Frama-C uses 32-bit
 # architecture we need to make sure that same architecture is used for
 # instrumentation and for compilation.
 MACHDEPFLAGS="`getconf LONG_BIT`"
 # Check if getconf gives out the value accepted by Frama-C/GCC
-echo "$MACHDEPFLAGS" | grep '16\|32\|64' \
+echo "$MACHDEPFLAGS" | grep '16\|32\|64' 2>&1 >/dev/null \
   || error "$MACHDEPFLAGS-bit architecture not supported"
 # -machdep option sent to frama-c
 MACHDEP="-machdep gcc_x86_$MACHDEPFLAGS"
@@ -66,39 +73,58 @@ CPPMACHDEP="-D__FC_MACHDEP_X86_$MACHDEPFLAGS"
 # GCC machine option
 GCCMACHDEP="-m$MACHDEPFLAGS"
 
+# Macro that identifies E-ACSL compilation. Passed to Framac and GCC runs
+# but not to the original compilation
+EACSL_MACRO_ID="__E_ACSL__"
+
 # Gcc
 CC="`check_tool 'gcc'`"
 CFLAGS="-std=c99 $GCCMACHDEP -g3 -O2 -pedantic -fno-builtin -Wall \
     -Wno-long-long \
     -Wno-attributes \
+    -Wno-unused \
+    -Wno-unused-function \
     -Wno-unused-result \
     -Wno-unused-value \
     -Wno-unused-function \
     -Wno-unused-variable \
     -Wno-unused-but-set-variable \
-    -Wno-implicit-function-declaration \
-    -Wno-attributes"
+    -Wno-implicit-function-declaration"
 CPPFLAGS=""
 LDFLAGS=""
-# Frama-C
-FRAMAC="`check_tool 'frama-c'`"
-FRAMAC_CONGIG="`check_tool 'frama-c-config'`"
-FRAMAC_FLAGS="-implicit-function-declaration ignore"
 
 # E-ACSL source that needed for compilation
-FRAMA_C_SHARE="`$FRAMAC_CONGIG -print-share-path`"
 EACSL_SHARE="$FRAMA_C_SHARE/e-acsl"
-RTL="$EACSL_SHARE/e_acsl.c                      \
-  $EACSL_SHARE/memory_model/e_acsl_mmodel.c     \
-  $EACSL_SHARE/memory_model/e_acsl_bittree.c    \
+RTL_BITTREE="\
+  $EACSL_SHARE/e_acsl.c \
+  $EACSL_SHARE/memory_model/e_acsl_mmodel.c \
+  $EACSL_SHARE/memory_model/e_acsl_bittree.c \
+"
+RTL_SPLAYTREE="\
+  $EACSL_SHARE/e_acsl.c \
+  $EACSL_SHARE/memory_model/e_acsl_splay_tree.c \
+  $EACSL_SHARE/memory_model/e_acsl_mmodel.c \
+"
+RTL_TREE="\
+  $EACSL_SHARE/e_acsl.c \
+  $EACSL_SHARE/memory_model/e_acsl_tree.c \
+  $EACSL_SHARE/memory_model/e_acsl_mmodel.c \
+"
+RTL_LIST="\
+  $EACSL_SHARE/e_acsl.c \
+  $EACSL_SHARE/memory_model/e_acsl_list.c \
+  $EACSL_SHARE/memory_model/e_acsl_mmodel.c \
 "
 
-# CPP and LD flags for compilation of E-ACSL-generated sources
-EACSL_CPP_FLAGS="
-    -D__FC_errno=(*__errno_location())
-    -D__builtin_printf=printf
-    -D__builtin_memcpy=memcpy"
-EACSL_LD_FLAGS="-lgmp -lm"
+RTL="$RTL_BITTREE"
+
+# C, CPP and LD flags for compilation of E-ACSL-generated sources
+EACSL_CFLAGS=""
+EACSL_CPPFLAGS="
+    -I$EACSL_SHARE
+    -D$EACSL_MACRO_ID
+    -D__FC_errno=(*__errno_location())"
+EACSL_LDFLAGS="-lgmp -lm"
 
 # Variables holding getopt options
 OPTION_FRAMAC_EXTRA=                     # Extra Frama-C options
@@ -114,7 +140,14 @@ OPTION_EACSL="-e-acsl -then-last"        # Specifies E-ACSL run
 OPTION_FRAMA_STDLIB="-no-frama-c-stdlib" # Use Frama-C stdlib
 OPTION_FULL_MMODEL=                      # Instrument as much as possible
 OPTION_GMP=                              # Use GMP integers everywhere
-OPTION_EXTRA_CPP="-I$FRAMA_C_SHARE/libc $CPPMACHDEP" # Extra CPP flags
+OPTION_DEBUG_MACRO="-DE_ACSL_DEBUG"      # Debug macro
+OPTION_DEBUG_LOG_MACRO=""                # Specification of debug log file
+# The following option controls whether to use gcc builtins
+# (e.g., __builtin_strlen) in RTL or fall back to custom implementations
+# of standard functions.
+OPTION_BUILTINS="-DE_ACSL_BUILTINS"
+# Extra CPP flags for frama-c
+OPTION_EXTRA_CPP="-D$EACSL_MACRO_ID -I$FRAMA_C_SHARE/libc $CPPMACHDEP"
 
 manpage() {
   echo "NAME"
@@ -134,38 +167,56 @@ manpage() {
   echo "      compile input files as if they were generated by E-ACSL"
   echo "  -p, --print"
   echo "      output the code generated by E-ACSL to STDOUT"
-  echo "  -d, --debug <N>"
+  echo "  -d, --debug=<N>"
   echo "      pass a value to Frama-C -debug option"
-  echo "  -o, --ocode <FILENAME>"
+  echo "  -o, --ocode=<FILENAME>"
   echo "      name of the output source file, defaults to a.out.frama.c"
-  echo "  -O, --oexec <FILENAME>"
+  echo "  -O, --oexec=<FILENAME>"
   echo "      name of the executable generated from the un-instrumented code."
   echo "      Executable compiled from the E-ACSL instrumented sources is"
   echo "      appended .e.acsl suffix. Defaults to a.out and a.out.e-acsl"
-  echo "  -v, --verbose <N>"
+  echo "  -v, --verbose=<N>"
   echo "      pass a value to Frama-C -verbose option"
   echo "  -f, --frama-c-only"
   echo "      run input source files through Frama-C without E-ACSL"
-  echo "  -E, --extra-cpp-args <FLAGS>"
+  echo "  -E, --extra-cpp-args=<FLAGS>"
   echo "      pass additional arguments to the Frama-C pre-processor"
-  echo "  -R, --rtl"
-  echo "      output E_ACSL runtime libraries to STDOUT"
   echo "  -L, --frama-c-stdlib"
   echo "      use Frama-C standard library"
   echo "  -M, --full-mmodel"
   echo "      maximise memory-related instrumentation"
   echo "  -g, --gmp"
   echo "      always use GMP integers instead of C integral types"
-  echo "  -l, --ld-flags <FLAGS>"
+  echo "  -l, --ld-flags=<FLAGS>"
   echo "      pass the specified flags to the linker"
-  echo "  -e, --cpp-flags <FLAGS>"
+  echo "  -e, --cpp-flags=<FLAGS>"
   echo "      pass the specified flags to the pre-processor (compile-time)"
   echo "  -q, --quiet"
   echo "      suppress any output except for errors and warnings"
-  echo "  -s, --logfile <FILE>"
+  echo "  -s, --logfile=<FILE>"
   echo "      redirect all output to a given log file"
   echo "  -F, --frama-c-extra <OPTION>"
   echo "      pass an extra option to frama-c invocation"
+  echo "  -m, --memory-model=<bittree|tree|list|splaytree>"
+  echo "      memory model (i.e., runtime library) to be used at compile time."
+  echo "      Valid arguments are:"
+  echo "        bittree     - memory modelling using a Patricie trie ADT"
+  echo "        splaytree   - memory modelling using a splay tree ADT"
+  echo "        list        - memory modelling using a linked-list ADT"
+  echo "        tree        - memory modelling using a binary tree ADT"
+  echo "  -P, --production"
+  echo "      Compile optimized executatle without debug features"
+  echo "  -N, --no-stdlib"
+  echo "      If specified the E-ACSL run-time library uses custom  "
+  echo "      implementations of standard library functions (such as memset)."
+  echo "      By default GCC builtins are used (e.g., __builtin_memset)."
+  echo "  -D, --debug-log=<FILE>"
+  echo "      Specify the name of the file for logging of debugging output of"
+  echo "      modified modified executables. If '-' is specified then the"
+  echo "      output is redirected to the standard error stream. By default  "
+  echo "      /tmp/e-acsl.log file is used. Note that this option is meaningful"
+  echo "      in the absence of the -P flag, which diables debug logging for  "
+  echo "      performance reasons."
   echo ""
   echo "EXAMPLES:"
   echo "  # Instrument foo.c and output the instrumented code to a.out.frama.c"
@@ -275,7 +326,7 @@ do
     # Additional CPP arguments
     --extra-cpp-args|-E)
       shift;
-      OPTION_EXTRA_CPP="$OPTION_EXTRA_CPP$1"
+      OPTION_EXTRA_CPP="$OPTION_EXTRA_CPP $1"
       shift;
     ;;
     # Additional flags passed to the linker
@@ -303,11 +354,6 @@ do
       shift;
       OPTION_EACSL=
     ;;
-    # Output the RTL files
-    --rtl|-R)
-      echo $RTL
-      exit 0;
-    ;;
     # Do use Frama-C stdlib, which is the default behaviour of Frama-C
     --frama-c-stdlib|-L)
       shift;
@@ -323,6 +369,41 @@ do
       shift;
       OPTION_GMP="-e-acsl-gmp-only"
     ;;
+    -P|--production)
+      shift;
+      OPTION_DEBUG_MACRO=""
+    ;;
+    -N|--no-stdlib)
+      shift;
+      OPTION_BUILTINS=""
+    ;;
+    -D|--debug-log)
+        shift;
+        OPTION_DEBUG_LOG_MACRO="-DE_ACSL_DEBUG_LOG=$1"
+        shift;
+    ;;
+    -m|--memory-model)
+      shift;
+      mmodel="$1"
+      shift;
+      case $mmodel in
+        bittree)
+          RTL="$RTL_BITTREE"
+        ;;
+        splaytree)
+          RTL="$RTL_SPLAYTREE"
+        ;;
+        tree)
+          RTL="$RTL_TREE"
+        ;;
+        list)
+          RTL="$RTL_LIST"
+        ;;
+        *)
+          error "Unknown model memory model: '$mmodel'"
+        ;;
+      esac
+    ;;
   esac
 done
 shift;
@@ -368,8 +449,17 @@ if test -n "$OPTION_COMPILE"  ; then
     OPTION_OCODE="$@"
   fi
   # Compile and link E-ACSL-instrumented file
-  ($OPTION_ECHO; $CC $CPPFLAGS $CFLAGS $EACSL_CPP_FLAGS $RTL \
-    "$OPTION_OCODE" -o "$OPTION_OEXEC.e-acsl" $LDFLAGS $EACSL_LD_FLAGS)
+  ($OPTION_ECHO; \
+   $CC \
+     $CFLAGS $CPPFLAGS \
+     $EACSL_CFLAGS $EACSL_CPPFLAGS \
+     $RTL \
+     $OPTION_DEBUG_MACRO \
+     $OPTION_DEBUG_LOG_MACRO \
+     $OPTION_BUILTINS \
+     -o "$OPTION_OEXEC.e-acsl" \
+     "$OPTION_OCODE" \
+     $LDFLAGS $EACSL_LDFLAGS)
   error "fail to compile/link instrumented code: $@" $?;
 fi
 exit 0;
diff --git a/src/plugins/e-acsl/scripts/testrun.sh b/src/plugins/e-acsl/scripts/testrun.sh
new file mode 100755
index 00000000000..3bcfe997c86
--- /dev/null
+++ b/src/plugins/e-acsl/scripts/testrun.sh
@@ -0,0 +1,97 @@
+##########################################################################
+#                                                                        #
+#  This file is part of the Frama-C's E-ACSL plug-in.                    #
+#                                                                        #
+#  Copyright (C) 2012-2015                                               #
+#    CEA (Commissariat à l'énergie atomique et aux énergies              #
+#         alternatives)                                                  #
+#                                                                        #
+#  you can redistribute it and/or modify it under the terms of the GNU   #
+#  Lesser General Public License as published by the Free Software       #
+#  Foundation, version 2.1.                                              #
+#                                                                        #
+#  It is distributed in the hope that it will be useful,                 #
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of        #
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         #
+#  GNU Lesser General Public License for more details.                   #
+#                                                                        #
+#  See the GNU Lesser General Public License version 2.1                 #
+#  for more details (enclosed in the file license/LGPLv2.1).             #
+#                                                                        #
+##########################################################################
+
+#!/bin/sh -e
+
+# Convenience script for running tests with E-ACSL. Given a source file the
+# sequence is as follows:
+#   1. Perform E-ACSL instrumentation
+#   2. Compile instrumented and original files
+#   3. Compare outputs of the above
+
+# Arguments:
+#   $1 - base name of the source file to use (e.g., addrOf)
+#   $2 - base name of the test suite directory the test file is located in.
+#     (for instance e-acsl-runtime). Provided that ROOT is the directory
+#     holding the E-ACSL repository there should be either:
+#     $ROOT/test/e-acsl-runtime/addrOf.i or
+#     $ROOT/test/e-acsl-runtime/addrOf.c
+#   $3 - if specified this script re-runs test sequence generating using
+#       -e-acsl-gmp-only option
+
+PREFIX="$1" # Prefix (test suite) directory, e.g., bts, e-acsl-runtime
+TEST="$2" # Based name of the test file with extension stripped
+GMP="$3" # Whether to use a subsequent run with -e-acsl-gmp-only
+
+ROOTDIR="`readlink -f $(dirname $0)/../`" # Root directory of the repository
+TESTDIR="$ROOTDIR/tests/$PREFIX"
+RESDIR=$TESTDIR/result # result directory within the test suite
+TESTFILE=`ls $TESTDIR/$TEST.[ic]` # Source test file
+MODEL="bittree" # Memory model to link against.
+
+LOG="$RESDIR/$TEST.testrun" # Base name for log files
+OUT="$RESDIR/gen_$TEST"     # Base name for output
+RUNS=1
+
+# Remove all old logs and executables before running new tests
+rm -f $LOG.* $OUT.*
+
+# Error reporting
+error() {
+  echo "Error: $1" 1>&2
+  echo "See $2 for details" 1>&2
+  exit 1
+}
+
+# Instrument the given test using e-acsl-gcc.sh and compare outputs of the
+# executables generated from instrumented and non-instrumented sources
+run_test() {
+  local ocode=$OUT.$RUNS.c # Generated source file
+  local logfile=$LOG.$RUNS.elog # Log file for e-acsl-gcc.sh output
+  local oexec=$OUT.$RUNS.out # Generated executable name
+  local oexeclog=$LOG.$RUNS.rlog # Log for executable output
+  local extra="$1" # Additional arguments to e-acsl-gcc.sh
+
+  # Command for instrumenting the source file and compiling the original
+  # and the instrumented code
+  EACSL_GCC="e-acsl-gcc.sh
+    --compile $TESTFILE --ocode=$ocode --logfile=$logfile
+    --memory-model=$MODEL --oexec=$oexec $extra"
+
+  $EACSL_GCC || error "Command $EACSL_GCC failed" "$logfile"
+
+  # Log outputs of the generated executables
+  $oexec         2>&1 > $oexeclog.native
+  $oexec.e-acsl  2>&1 > $oexeclog.e-acsl
+
+  ## Make sure that instrumented and uninstrumented programs have same outputs
+  diff $oexeclog.native $oexeclog.e-acsl ||
+    error "Output of programs before and after instrumentation differ" \
+      "output of $oexec and $oexec.e-acsl"
+
+  RUNS=$((RUNS+1))
+}
+
+run_test
+if test -n "$GMP"; then
+  run_test "--gmp"
+fi
-- 
GitLab