| #!/usr/bin/env bash |
| # This script verifies expression folding. |
| # It compiles a source file with '-fdebug-dump-symbols' and looks for |
| # parameter declarations to check they have been folded as expected. |
| # To check folding of an expression EXPR, the fortran program passed to this script |
| # must contain the following: |
| # logical, parameter :: test_x = <compare EXPR to expected value> |
| # This script will test that all parameter with a name starting with "test_" have |
| # been folded to .true. |
| # For instance, acos folding can be tested with: |
| # |
| # real(4), parameter :: res_acos = acos(0.5_4) |
| # real(4), parameter :: exp_acos = 1.047 |
| # logical, parameter :: test_acos = abs(res_acos - exp_acos).LE.(0.001_4) |
| # |
| # There are two kinds of failure: |
| # - test_x is folded to .false.. This means the expression was folded |
| # but the value is not as expected. |
| # - test_x is not folded (it is neither .true. nor .false.). This means the |
| # compiler could not fold the expression. |
| |
| if [[ $# < 3 ]]; then |
| echo "Usage: $0 <fortran-source> <temp test dir> <f18-executable>" |
| exit 1 |
| fi |
| |
| src=$1 |
| [[ ! -f $src ]] && echo "File not found: $src" && exit 1 |
| shift |
| |
| temp=$1 |
| mkdir -p $temp |
| shift |
| |
| CMD="$* -fdebug-dump-symbols -fparse-only" |
| |
| # Check if tests should assume folding is using libpgmath |
| if [[ $LIBPGMATH ]]; then |
| CMD="$CMD -DTEST_LIBPGMATH" |
| echo "Assuming libpgmath support" |
| else |
| echo "Not assuming libpgmath support" |
| fi |
| |
| src1=$temp/symbols.log |
| src2=$temp/all_parameters.log |
| src3=$temp/tested_parameters.log |
| src4=$temp/failures.log |
| messages=$temp/messages.log |
| actual_warnings=$temp/actwarnings.log |
| expected_warnings=$temp/expwarnings.log |
| warning_diffs=$temp/warnings.diff |
| |
| if ! ( cd $temp; $CMD $src ) > $src1 2> $messages # compile, dumping symbols |
| then |
| cat $messages |
| echo FAIL compilation |
| exit 1 |
| fi |
| |
| # Get all PARAMETER declarations |
| sed -e '/, PARAMETER/!d' -e 's/, PARAMETER.*init:/ /' \ |
| -e 's/^ *//' $src1 > $src2 |
| |
| # Collect test results |
| sed -e '/^test_/!d' $src2 > $src3 |
| |
| # Check all tests results (keep tests that do not resolve to true) |
| sed -e '/\.true\._.$/d' $src3 > $src4 |
| |
| |
| #Check warnings |
| sed -n 's=^[^:]*:\([0-9]*\):[0-9]*: =\1: =p' $messages > $actual_warnings |
| |
| awk ' |
| BEGIN { FS = "!WARN: "; } |
| /^ *!WARN: / { warnings[nwarnings++] = $2; next; } |
| { for (i = 0; i < nwarnings; ++i) printf "%d: %s\n", NR, warnings[i]; nwarnings = 0; } |
| ' $src > $expected_warnings |
| |
| diff -U0 $actual_warnings $expected_warnings > $warning_diffs |
| |
| if [ -s $src4 ] || [ -s $warning_diffs ]; then |
| echo "folding test failed:" |
| # Print failed tests (It will actually print all parameters |
| # that have the same suffix as the failed test so that one can get more info |
| # by declaring expected_x and result_x for instance) |
| if [[ -s $src4 ]]; then |
| sed -e 's/test_/_/' -e 's/ .*//' $src4 | grep -f - $src2 |
| fi |
| if [[ -s $warning_diffs ]]; then |
| echo "$cmd" |
| < $warning_diffs \ |
| sed -n -e 's/^-\([0-9]\)/actual at \1/p' -e 's/^+\([0-9]\)/expect at \1/p' \ |
| | sort -n -k 2 |
| fi |
| echo FAIL |
| exit 1 |
| else |
| passed_results=$(wc -l < $src3) |
| passed_warnings=$(wc -l < $expected_warnings) |
| passed=$(($passed_warnings + $passed_results)) |
| echo all $passed tests passed |
| echo PASS |
| fi |