#!/bin/bash
#
# Copyright (C) 2008 Uday Bondhugula
# 
# Available under GNU GPL v2
#
# Automatic annotation generation for unrolling
# Unroll/jammable loops are detected in the transformation
# framework. The purpose of the script is just to read the
# .unroll generated, generate and insert annotations that 
# will cause ancc to do the job.
#
# Don't bother to read anything below
#

match_closing_brace() {
    grep -n [{}] $1 > loopopenclose
    sed -n -e '/^'$2':/,$p' loopopenclose > cut

    open=0
    numclose=0
    while read -n1 char; do
        if [ "$char" = "{" ]; then
            open=$(($open+1))
        elif [ "$char" = "}" ]; then
            numclose=$(($numclose+1))
            open=$(($open-1))
            if [ $open -eq 0 ]; then
                break
            fi
        fi
    done <cut

    cat cut | grep "}" > closecut
    closing_brace_linenum=`sed -n -e ''$numclose'p' closecut | awk '{split($1,t,":"); print t[1]}'`
    rm -f cut loopopenclose closecut
    return $closing_brace_linenum
}

if [ ! -f .unroll ]; then
    exit 2
fi

numloops=`wc -l .unroll | awk '{print $1}'`

if [ $numloops -eq 0 ]; then
    exit 3
fi

# Generate the unrolling annotation 

# unroll only two
unrolldim1=`sed -n -e '1p' .unroll | awk '{print $1}'`
unrolldim2=`sed -n -e '2p' .unroll | awk '{print $1}'`

unrollcmd1=`sed -n -e '1p' .unroll | awk '{print $2}'`
unrollcmd2=`sed -n -e '2p' .unroll | awk '{print $2}'`

ufactor1=`sed -n -e '1p' .unroll | awk '{print $3}'`
ufactor2=`sed -n -e '2p' .unroll | awk '{print $3}'`

if [ $numloops -ne 1 ]; then
    # 2 loops to unroll
    dirname=`dirname $1`

    # find the unrollable hotspot with $unrolldim1 and $unrolldim2
    params=""
    while read n; do
	params=$n\\\|$params; 
    done < .params;
#    for i in `sed -n 1,2p .params`; do params=$i\\\|$params; done
    params=$params"phony"
    num=""
    # don't even bother to ask what this is - the lowest levels I have stooped to
    for i in `grep -n  "for ($unrolldim1" $1 | grep -v $params | awk '{split($1,t,":"); print t[1]}'`  ; do grep -n ".*" $1 |  sed -n -e \
        ''$(($i+1))'p'  | grep "for ($unrolldim2" | grep -q -v "$params" ; if [ "$?" = "0" ]; then  num="$i"; break; fi 
    done
    # if no loops with bounds free of parameters are found, just go for those
    # with params in them
    if [ "$num" = "" ]; then
        for i in `grep -n  "for ($unrolldim1" $1 | awk '{split($1,t,":"); print t[1]}'` ; do grep -n ".*" $1 |  sed -n -e \
            ''$(($i+1))'p'  | grep "for ($unrolldim2" | grep -q -v "$params" ; if [ "$?" = "0" ]; then  num="$i"; break; fi 
        done

        # selling my soul to the devil now
        if [ "$num" = "" ]; then
            for i in `grep -n  "for ($unrolldim1" $1 | awk '{split($1,t,":"); print t[1]}'` ; do grep -n ".*" $1 |  sed -n -e \
                ''$(($i+1))'p'  | grep -q "for ($unrolldim2" ; if [ "$?" = "0" ]; then  num="$i"; break; fi 
            done
        fi
    fi

    if [ "$num" = "" ]; then
	### LNP: Put this to 0 instead of 4. Now we do not crash if we
	### try to unroll-and-jam a non-perfectly nested loop. This
	### fix is WRONG: we should not generate a .unroll which
	### specifies such an unrolling.
        exit 0
    fi

    #echo "[PLann] Found unrollable nest at $num of $1"
    echo "[PLann] Found unrollable nest"
    match_closing_brace "$1" "$num"
    annotation_end_line_num=$?

    sed -n -e '1,'$(($num-1))'p' $1 > .header
    echo "{" > .unrollbody
    sed -n -e ''$(($num+2))','$(($annotation_end_line_num-2))'p' $1 >> .unrollbody
    echo "}" >> .unrollbody
    #cat .unrollbody

    sed -n -e ''$num'p' $1 | tr -d "{" > .unroll1
    sed -n -e ''$(($num+1))'p' $1 | tr -d "{" > .unroll2

    echo "/*@ begin Loop(" > .annotation
    echo "transform $unrollcmd1(ufactor=$ufactor1)" >> .annotation
    cat .unroll1 >> .annotation
    echo "transform $unrollcmd2(ufactor=$ufactor2)" >> .annotation
    cat .unroll2 >> .annotation
    cat .unrollbody >> .annotation
    echo ") @*/" >> .annotation

    echo "/*@ end @*/" > .annotation_end

    sed -n -e ''$(($num+1))'p' $1 | tr -d "{" > .unroll2

    sed -n -e ''$num','$annotation_end_line_num'p' $1 > .middle
    sed -n -e ''$(($annotation_end_line_num+1))',$p' $1 > .footer

else
    # Only 1 loop to unroll
    dirname=`dirname $1`

    # Find the unrollable loop(s)
    params=""
    while read n; do
	params=$n\\\|$params; 
    done < .params;
    params=$params"phony"

    num=""
    # don't even bother to ask what this is - the lowest levels I have stooped to
    num=`grep -n  "for ($unrolldim1" $1 | grep -v $params | awk '{split($1,t,":"); print t[1]}' | head -n 1`

    # if no loops with bounds free of parameters are found, just go for those
    # with params in them
    if [ "$num" = "" ]; then
        num=`grep -n  "for ($unrolldim1" $1 | awk '{split($1,t,":"); print t[1]}'  | head -n 1`
    fi

    if [ "$num" = "" ]; then
        exit 4
    fi

    echo "[PLann] Found unrollable nest" # at line $num of $1"
    match_closing_brace $1 $num
    annotation_end_line_num=$?

    sed -n -e '1,'$(($num-1))'p' $1 > .header
    echo "{" > .unrollbody
    sed -n -e ''$(($num+1))','$(($annotation_end_line_num-1))'p' $1 >> .unrollbody
    echo "}" >> .unrollbody
    #cat .unrollbody

    sed -n -e ''$num'p' $1 | tr -d "{" > .unroll1

    echo "/*@ begin Loop(" > .annotation
    echo "transform $unrollcmd1(ufactor=$ufactor1)" >> .annotation
    cat .unroll1 >> .annotation
    cat .unrollbody >> .annotation
    echo ") @*/" >> .annotation

    echo "/*@ end @*/" > .annotation_end

    sed -n -e ''$num','$annotation_end_line_num'p' $1 > .middle
    sed -n -e ''$(($annotation_end_line_num+1))',$p' $1 > .footer
fi

cat .header .annotation .middle .annotation_end .footer > $1

# run the annotation generator
export ANNOTATIONS_DIR=$2
ANCC="$ANNOTATIONS_DIR/bin/ancc"

$ANCC $1 $1.ancc
cp -f $1 .ancc
mv -f $1.ancc $1
echo "[PLann] Finished running ancc"

rm -f .header .lb .ub .header .footer .vecloop .middle .footer .annotation .annotation_end .unroll1 .unroll2 .unrollbody .ancc .unroll
exit 0
