#! /bin/sh
#---------------------------------------------------------------------------#
# vim: ts=4 sw=4 expandtab ft=sh
#---------------------------------------------------------------------------#
# scripts/mgnuc.  Generated from mgnuc.in by configure.
#---------------------------------------------------------------------------#
# Copyright (C) 1995-2007, 2010-2012 The University of Melbourne.
# Copyright (C) 2013-2020 The Mercury team.
# This file may only be copied under the terms of the GNU General
# Public License - see the file COPYING in the Mercury distribution.
#---------------------------------------------------------------------------#
#
# IMPORTANT: the manpage is produced automatically from this help
# message, so if you change the help message, don't forget to check
# that the manpage still looks OK.

# *************************************************************************
# *** IMPORTANT NOTE: any changes to this file may also require similar ***
# *** changes to compiler/compile_target_code.m                         ***
# *************************************************************************

FULLARCH=x86_64-pc-linux-gnu

DEFAULT_GRADE=${MERCURY_DEFAULT_GRADE=asm_fast.gc}
CC=${MERCURY_C_COMPILER="x86_64-pc-linux-gnu-gcc"}
C_COMPILER_TYPE=${MERCURY_C_COMPILER_TYPE="gcc_14_2_1"}
CFLAGS_FOR_REGS="-fno-builtin -fno-omit-frame-pointer -fno-reorder-functions"
CFLAGS_FOR_GOTOS="-fno-defer-pop -fno-function-cse -fno-gcse -fno-move-loop-invariants -fno-tree-dominator-opts -fno-tree-slp-vectorize -fno-reorder-functions -ftrack-macro-expansion=0 -fno-diagnostics-show-caret"
CFLAGS_FOR_THREADS="-DGC_THREADS -D_THREAD_SAFE -D_REENTRANT"
CFLAGS_FOR_LTO=""
CFLAGS_FOR_NO_STRICT_ALIASING="-fno-strict-aliasing"
CFLAGS_FOR_ANSI=""
CFLAGS_FOR_SANITIZERS=""
BYTES_PER_WORD="8"
MKTEMP=/usr/bin/mktemp
TMPDIR=${TMPDIR=/tmp}

case "${C_COMPILER_TYPE}" in
    gcc*)
        ANSI_OPTS="${CFLAGS_FOR_ANSI}"
        CHECK_OPTS="
            -Wall -Wwrite-strings
            -Wshadow -Wstrict-prototypes -Wmissing-prototypes -Wno-unused"

# Note: we do not enable the following gcc warnings:
# -Wredundant-decls     causes too many complaints in system header files
# -Wpointer-arith       causes too many complaints in system header files
#                       (fixed in gcc 3.0, though, so at some point
#                       we should re-enable this)
# -Wtraditional         we don't care about compatibility with pre-ANSI C
# -Wconversion          really only intended to help people using \`unprotoize'
# -Waggregate-return    not useful, IMHO

# -Wcast-qual           causes LOTS of redundant warnings
# -Wcast-align          causes redundant warnings in memory.c
# -pedantic             causes unsuppressable warnings about LVALUE_CAST()
# -Wnested-externs      causes unsuppressable warnings about callentry()
# -Wid-clash-31         causes warnings about entry_mercury__xxx ...
#                       we don't care about compatibility with C compilers
#                       that have short fixed limits on identifier length
# -Wenum-clash          is for C++ only
# -Wunused              causes various spurious warnings

        # Enabling -fomit-frame-pointer causes setjmp/longjmp to misbehave
        # with MinGW on Windows XP.
        case "${FULLARCH}" in
            *mingw*)
              OPT_OPTS="-O2 ${CFLAGS_FOR_NO_STRICT_ALIASING}"
              ;;
            *)
              OPT_OPTS="-O2 ${CFLAGS_FOR_NO_STRICT_ALIASING} -fomit-frame-pointer"
              ;;
        esac
        DEBUG_OPTS="-g"
        DISABLE_OPTS_OPT="-O0"
        COMPILER_HALT_AT_WARN_OPT="-Werror"
        COMPILER=gcc
        ;;
    clang*)
        ANSI_OPTS=
        CHECK_OPTS="-w"
        OPT_OPTS="-O0 ${CFLAGS_FOR_NO_STRICT_ALIASING} -fomit-frame-pointer"
        DEBUG_OPTS="-g"
        DISABLE_OPTS_OPT="-O0"
        COMPILER_HALT_AT_WARN_OPT="-Werror"
        COMPILER=clang
        ;;
    msvc*)
        ANSI_OPTS=""
        CHECK_OPTS="-nologo"    # Suppress the MSVC banner message.
        OPT_OPTS="-O1"
        # See README.MS-VisualC for why we don't enable C level debugging.
        #DEBUG_OPTS="-Zi"
        DEBUG_OPTS=""
        DISABLE_OPTS_OPT="-Od"
        COMPILER_HALT_AT_WARN_OPT=""
        COMPILER=cl
        ;;
    *)
        ANSI_OPTS=
        CHECK_OPTS=
        OPT_OPTS="-O"
        DEBUG_OPTS="-g"
        DISABLE_OPTS_OPT="-O0"
        COMPILER_HALT_AT_WARN_OPT=""
        COMPILER=unknown
        ;;
esac

SPLIT_OPTS=""
INLINE_ALLOC_OPTS=""

verbose=false
c_debug=false
c_optimize=true
use_activation_counts=false
preserve_tail_recursion=true
mercury_config_dir=${MERCURY_STDLIB_DIR-/usr/lib64/mercury}
mercury_config_dir=${MERCURY_CONFIG_DIR=${mercury_config_dir}}
mercury_stdlib_dir=${MERCURY_STDLIB_DIR=/usr/lib64/mercury}
do_filter_cc=true
halt_at_warn_if_possible=false

# include the file `init_grade_options.sh-subr'
#---------------------------------------------------------------------------#
# vim: ts=4 sw=4 expandtab ft=sh
#---------------------------------------------------------------------------#
# Copyright (C) 1997-2007, 2010 The University of Melbourne.
# Copyright (C) 2013-2014, 2016-2017, 2020 The Mercury team.
# This file may only be copied under the terms of the GNU General
# Public License - see the file COPYING in the Mercury distribution.
#---------------------------------------------------------------------------#
#
# init_grade_options.sh-subr:
#	An `sh' subroutine for initializing grade-related options.
#	Used by the `ml', `mgnuc' and `c2init' scripts.
#
#	The code here should be inserted before a script's option-parsing
#	loop.  The invoking script must define a DEFAULT_GRADE option.
#
# IMPORTANT: any changes to the handling of grades here may also require
# changes to all the files indicated by runtime/mercury_grade.h.
#
# This file must initialize all the shell variables used by
# parse_grade_options.sh-subr, and must list all the options processed in
# parse_grade_options.sh-subr.
#
#---------------------------------------------------------------------------#

grade_usage="\
Grade options:
	-s <grade>, --grade <grade>
	--target {c, csharp, java}
	--asm-labels
	--gcc-non-local-gotos
	--gcc-global-registers
	-H, --high-level-code
	--parallel
	--gc {boehm, boehm_debug, hgc, accurate, none}
	-p, --profiling
	--profile-calls
	--profile-time
	--profile-memory
	--profile-deep
	--record-term-sizes-as-words
	--record-term-sizes-as-cells
	--use-trail
	--use-trail-segments
	--reserve-tag
	--use-minimal-model-stack-copy
	--use-minimal-model-own-stacks
	--minimal-model-debug
	--single-prec-float
	--pic-reg
	--no-stack-trace
	--debug
	--decl-debug
	--ss-debug
	--low-level-debug
	--extend-stacks-when-needed
	--stack-segments
	--use-regions
		See the documentation in the \"Invocation\" section
		of the Mercury User's Guide."

# --use-regions-debug and --use-regions-profiling are not yet documented
#		since they are not yet stable

target=c
highlevel_code=false
asm_labels=true
non_local_gotos=true
global_regs=true
thread_safe=false
threadscope=false
gc_method=boehm
profile_time=false
profile_calls=false
profile_memory=false
profile_deep=false
record_term_sizes_as_words=false
record_term_sizes_as_cells=false
use_trail=false
use_minimal_model_stack_copy=false
use_minimal_model_own_stacks=false
minimal_model_debug=false
pregenerated_dist=false
single_prec_float=false
debug=false
decl_debug=false
ss_debug=false
ll_debug=false
extend_stacks=false
stack_segments=false
use_regions=false
use_regions_debug=false
use_regions_profiling=false

case $# in
	0)
        set - --grade "$DEFAULT_GRADE"
        ;;
	*)
        set - --grade "$DEFAULT_GRADE" "$@"
        ;;
esac

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

Help="\
Name:   mgnuc - Mercury front-end to GNU C
Usage:  mgnuc [<options>] [-- <gcc options>] files...
Options:
    -v, --verbose
        Echo gcc command before executing it.
    --no-ansi
        Use the full contents of system headers, rather than the ANSI subset.
    --no-check
        Don't enable any of gcc's warnings.
    --low-level-debug
        Enable low-level debugging of the C code. Useful only for Mercury
        system developers.
    -g, --c-debug
        Generate object files that can debugged with C debuggers such as gdb.
    --no-c-optimize
        Disable optimization by the C compiler.
    --inline-alloc
        Inline calls to the memory allocator.
    --mercury-standard-library-directory <directory>
    --mercury-stdlib-dir <directory>
        The directory containing the installed Mercury standard library.
    --no-mercury-standard-library-directory, --no-mercury-stdlib-dir
        Don't use an installed Mercury standard library.
    --no-filter-cc
        Do not filter warnings from the C compiler.
    --halt-at-warn-if-possible
        Convert warnings into errors if (a) the C compiler supports this,
        and (b) the grade is an MLDS grade. (LLDS grades get some warnings
        that cannot be avoided.)

${grade_usage}

Description:
    This runs gcc with the appropriate options for compiling Mercury programs.
    Normally it invokes gcc in ANSI mode with almost all warnings enabled,
    but this can be changed using the \`--no-ansi' or \`--no-check' options.
Environment variables:
    MERCURY_DEFAULT_GRADE.
Files:
    If the current directory contains a file named .mgnuc_copts, then mgnuc
    will assume that it contains C compiler options that should be included
    on the C compiler's command line. This is usually used to specify C
    compiler search paths.
"

while : ; do
    case "$1" in
        -h|--help|"-?")
            echo "${Help}"
            exit 0
            ;;

#---------------------------------------------------------------------------#
# vim: ts=4 sw=4 expandtab ft=sh
#---------------------------------------------------------------------------#
# Copyright (C) 2005 The University of Melbourne.
# This file may only be copied under the terms of the GNU General
# Public License - see the file COPYING in the Mercury distribution.
#---------------------------------------------------------------------------#
#
# mgnuc_file_opts.sh-subr:
#
# An `sh' subroutine for processing the mgnuc options that can be set from
# .mgnuc_opts files. It is included twice in mgnuc. Its implementation is
# bound tightly to the code of mgnuc.in; all the variables it manipulates
# come from there.
#
# At the moment, this includes only options that do not have arguments.
# This is because processing options with arguments is hard to do without
# overriding the argument vector, and there is no simple way to preserve
# the exact structure of the original argument vector *including* any spaces
# inside individual arguments. There is no real need (at least right now)
# for putting such options into .mgnuc_opts files.
#
#---------------------------------------------------------------------------#

        -v|--verbose)
            verbose=true
            ;;
        -v-|--no-verbose)
            verbose=false
            ;;

        --no-ansi)
            ANSI_OPTS=
            ;;

        --no-check)
            CHECK_OPTS=
            ;;

        --inline-alloc)
            INLINE_ALLOC_OPTS="-DMR_INLINE_ALLOC -DSILENT"
            ;;
        --no-inline-alloc)
            INLINE_ALLOC_OPTS=""
            ;;

        -g|--c-debug)
            c_debug=true
            ;;
        -g-|--no-c-debug)
            c_debug=false
            ;;

        --c-optimize)
            c_optimize=true
            ;;
        --no-c-optimize)
            c_optimize=false
            ;;

        --low-level-debug)
            low_level_debug=true
            ;;
        --no-low-level-debug)
            low_level_debug=false
            ;;

        --use-activation-counts)
            use_activation_counts=true
            ;;
        --no-use-activation-counts)
            use_activation_counts=false
            ;;

        --preserve-tail-recursion)
            preserve_tail_recursion=true
            ;;
        --no-preserve-tail-recursion)
            preserve_tail_recursion=false
            ;;

        --no-mercury-standard-library-directory|--no-mercury-stdlib-dir)
            unset mercury_stdlib_dir
            unset mercury_config_dir
            ;;

        --no-filter-cc)
            do_filter_cc=false
            ;;

        --halt-at-warn-if-possible)
            halt_at_warn_if_possible=true
            ;;

        --mercury-standard-library-directory|--mercury-stdlib-dir)
            mercury_stdlib_dir="$2"
            mercury_config_dir="$2"
            shift
            ;;

        --mercury-config-directory|--mercury-config-dir)
            mercury_config_dir="$2"
            shift
            ;;

        # We don't allow `MERCURY_CONFIG_DIR' to be unset
        # without `MERCURY_STDLIB_DIR' also being unset.

        # include the file `parse_grade_options.sh-subr'
#---------------------------------------------------------------------------#
# vim: ts=4 sw=4 expandtab ft=sh
#---------------------------------------------------------------------------#
# Copyright (C) 1997-2007, 2010 The University of Melbourne.
# Copyright (C) 2013-2014, 2016-2017, 2020 The Mercury team.
# This file may only be copied under the terms of the GNU General
# Public License - see the file COPYING in the Mercury distribution.
#---------------------------------------------------------------------------#
#
# parse_grade_options.sh-subr:
#   An `sh' subroutine for parsing grade-related options.
#   Used by the `ml', `mgnuc' and `c2init' scripts.
#
#   The code here should be inserted in the case statement in a script's
#   option-parsing loop.
#
# IMPORTANT: any changes to the handling of grades here may also require
# changes to all the files indicated by runtime/mercury_grade.h.
#
# This file should handle the setting of all the shell variables defined by
# init_grade_options.sh-subr.
#
#---------------------------------------------------------------------------#

    --target)
        shift
        case "$1" in
            c|C)
                target=c
                ;;
            csharp|'C#')
                target=csharp
                ;;
            java|Java)
                target=java
                ;;
            *)
                echo "$0: invalid target \`$1'" 1>&2
                exit 1
                ;;
        esac
        ;;

    --csharp|'--C#'|--csharp-only|'--C#-only')
        target=csharp
        ;;

    --java|--Java|--java-only|--Java-only)
        target=java
        ;;

    --high-level-code|-H)
        highlevel_code=true
        ;;
    --no-high-level-code|-H-)
        highlevel_code=false
        ;;

    --asm-labels)
        asm_labels=true
        ;;
    --no-asm-labels)
        asm_labels=false
        ;;

    --gcc-non-local-gotos)
        non_local_gotos=true
        ;;
    --no-gcc-non-local-gotos)
        non_local_gotos=false
        ;;

    --gcc-global-registers)
        global_regs=true
        ;;
    --no-gcc-global-registers)
        global_regs=false
        ;;

    --gc)
        shift
        case "$1" in
            accurate|conservative|boehm|boehm_debug|hgc|none|automatic)
                gc_method=$1
                ;;
            *)
                echo "$0: invalid gc method \`$1'" 1>&2
                exit 1
                ;;
        esac
        ;;

    --parallel)
        thread_safe=true
        ;;

    -p|--profiling|--time-profiling)
        profile_time=true
        profile_calls=true
        profile_memory=false
        profile_deep=false
        ;;
    --memory-profiling)
        profile_time=false
        profile_calls=true
        profile_memory=true
        profile_deep=false
        ;;
    --deep-profiling)
        profile_time=false
        profile_calls=false
        profile_memory=false
        profile_deep=true
        ;;
    -p-|--no-profiling)
        profile_time=false
        profile_calls=false
        profile_memory=false
        profile_deep=false
        ;;
    --profile-time)
        profile_time=true
        ;;
    --no-profile-time)
        profile_time=false
        ;;
    --profile-calls)
        profile_calls=true
        ;;
    --no-profile-calls)
        profile_calls=false
        ;;
    --profile-memory)
        profile_memory=true
        ;;
    --no-profile-memory)
        profile_memory=false
        ;;
    --profile-deep)
        profile_deep=true
        ;;
    --no-profile-deep)
        profile_deep=false
        ;;

    --record-term-sizes-as-words)
        record_term_sizes_as_words=true
        ;;
    --no-record-term-sizes-as-words)
        record_term_sizes_as_words=false
        ;;
    --record-term-sizes-as-cells)
        record_term_sizes_as_cells=true
        ;;
    --no-record-term-sizes-as-cells)
        record_term_sizes_as_cells=false
        ;;

    --use-trail)
        use_trail=true
        ;;
    --no-use-trail)
        use_trail=false
        ;;

    --use-minimal-model-stack-copy)
        use_minimal_model_stack_copy=true
        ;;
    --no-use-minimal-model-stack-copy)
        use_minimal_model_stack_copy=false
        ;;

    --use-minimal-model-own-stacks)
        use_minimal_model_own_stacks=true
        ;;
    --no-use-minimal-model-own-stacks)
        use_minimal_model_own_stacks=false
        ;;

    --minimal-model-debug)
        minimal_model_debug=true
        ;;
    --no-minimal-model-debug)
        minimal_model_debug=false
        ;;

    --pregenerated-dist)
        pregenerated_dist=true
        ;;
    --no-pregenerated-dist)
        pregenerated_dist=false
        ;;

    --single-prec-float)
        single_prec_float=true
        ;;
    --no-single-prec-float)
        single_prec_float=false
        ;;

    --debug)
        debug=true
        ;;
    --no-debug)
        debug=false
        ;;

    --decl-debug)
        decl_debug=true
        ;;
    --no-decl-debug)
        decl_debug=false
        ;;

    --ss-debug)
        ss_debug=true
        ;;
    --no-ss-debug)
        ss_debug=false
        ;;

    --low-level-debug)
        ll_debug=true
        ;;
    --no-low-level-debug)
        ll_debug=false
        ;;

    --extend-stacks-when-needed)
        extend_stacks=true
        ;;
    --no-extend-stacks-when-needed)
        extend_stacks=false
        ;;

    --stack-segments)
        stack_segments=true
        ;;
    --no-stack-segments)
        stack_segments=false
        ;;

    --use-regions)
        use_regions=true;;
    --no-use-regions)
        use_regions=false
        ;; 

    --use-regions-debug)
        use_regions_debug=true;;
    --no-use-regions-debug)
        use_regions_debug=false
        ;; 

    --use-regions-profiling)
        use_regions_profiling=true;;
    --no-use-regions-profiling)
        use_regions_profiling=false
        ;; 

    -s|--grade)
        shift
        grade="$1";

        # Convert a grade to a set of options.
        #
        # IMPORTANT: any changes to the handling of grades here
        # may also require changes to all the files indicated by
        # runtime/mercury_grade.h.

        target=c
        highlevel_code=false
        asm_labels=false
        non_local_gotos=false
        global_regs=false
        thread_safe=false
        gc_method=none
        profile_time=false
        profile_calls=false
        profile_memory=false
        profile_deep=false
        record_term_sizes_as_words=false
        record_term_sizes_as_cells=false
        use_trail=false
        use_minimal_model_stack_copy=false
        use_minimal_model_own_stacks=false
        minimal_model_debug=false
        pregenerated_dist=false
        single_prec_float=false
        debug=false
        decl_debug=false
        ss_debug=false
        ll_debug=false
        extend_stacks=false
        stack_segments=false
        use_regions=false
        use_regions_debug=false
        use_regions_profiling=false

        grade_pieces=`echo $grade | tr '.' ' '`
        for grade_piece in $grade_pieces
        do
            case "$grade_piece" in
                csharp)
                    target=csharp
                    asm_labels=false
                    non_local_gotos=false
                    global_regs=false
                    highlevel_code=true
                    ;;
                java)
                    target=java
                    asm_labels=false
                    non_local_gotos=false
                    global_regs=false
                    highlevel_code=true
                    ;;
                hlc)
                    asm_labels=false
                    non_local_gotos=false
                    global_regs=false
                    highlevel_code=true
                    ;;
                asm_fast)
                    target=c
                    asm_labels=true
                    non_local_gotos=true
                    global_regs=true
                    highlevel_code=false
                    ;;
                asm_jump)
                    target=c
                    asm_labels=true
                    non_local_gotos=true
                    global_regs=false
                    highlevel_code=false
                    ;;
                fast)
                    target=c
                    asm_labels=false
                    non_local_gotos=true
                    global_regs=true
                    highlevel_code=false
                    ;;
                jump)
                    target=c
                    asm_labels=false
                    non_local_gotos=true
                    global_regs=false
                    highlevel_code=false
                    ;;
                reg)
                    target=c
                    asm_labels=false
                    non_local_gotos=false
                    global_regs=true
                    highlevel_code=false
                    ;;
                none)
                    target=c
                    asm_labels=false
                    non_local_gotos=false
                    global_regs=false
                    highlevel_code=false
                    ;;

                par)
                    thread_safe=true
                    ;;

                threadscope)
                    threadscope=true
                    ;;

                agc)
                    gc_method=accurate
                    ;;
                gc)
                    gc_method=boehm
                    ;;
                hgc)
                    gc_method=hgc
                    ;;
                gcd)
                    gc_method=boehm_debug
                    ;;
                nogc)
                    gc_method=none
                    ;;

                memprof)
                    profile_time=false
                    profile_calls=true
                    profile_memory=true
                    profile_deep=false
                    ;;
                prof)
                    profile_time=true
                    profile_calls=true
                    profile_memory=false
                    profile_deep=false
                    ;;
                proftime)   
                    profile_time=true
                    profile_calls=false
                    profile_memory=false
                    profile_deep=false
                    ;;
                profcalls)  
                    profile_time=false
                    profile_calls=true
                    profile_memory=false
                    profile_deep=false
                    ;;
                profall)
                    profile_time=true
                    profile_calls=true
                    profile_memory=true
                    profile_deep=false
                    ;;
                profdeep)
                    profile_time=false
                    profile_calls=false
                    profile_memory=false
                    profile_deep=true
                    ;;

                tsw)
                    record_term_sizes_as_words=true
                    record_term_sizes_as_cells=false
                    ;;

                tsc)
                    record_term_sizes_as_words=false
                    record_term_sizes_as_cells=true
                    ;;

                tr)
                    use_trail=true
                    ;;

                trseg)
                    use_trail=true
                    ;;
                
                mm)
                    use_minimal_model_stack_copy=true
                    minimal_model_debug=false
                    ;;

                dmm)
                    use_minimal_model_stack_copy=true
                    minimal_model_debug=true
                    ;;

                mmsc)
                    use_minimal_model_stack_copy=true
                    minimal_model_debug=false
                    ;;

                dmmsc)
                    use_minimal_model_stack_copy=true
                    minimal_model_debug=true
                    ;;

                mmos)
                    use_minimal_model_own_stacks=true
                    minimal_model_debug=false
                    ;;

                dmmos)
                    use_minimal_model_own_stacks=true
                    minimal_model_debug=true
                    ;;

                pregen)
                    pregenerated_dist=true
                    ;;

                spf)
                    single_prec_float=true
                    ;;

                debug)
                    debug=true
                    ;;

                decldebug)
                    decl_debug=true
                    ;;

                ssdebug)
                    ss_debug=true
                    ;;

                ll_debug)
                    ll_debug=true
                    ;;

                exts)
                    extend_stacks=true
                    ;;

                stseg)
                    stack_segments=true
                    ;;

                rbmm)
                    use_regions=true
                    use_regions_debug=false
                    use_regions_profiling=false
                    ;;

                rbmmd)
                    use_regions=true
                    use_regions_debug=true
                    use_regions_profiling=false
                    ;;

                rbmmp)
                    use_regions=true
                    use_regions_debug=false
                    use_regions_profiling=true
                    ;;

                rbmmdp)
                    use_regions=true
                    use_regions_debug=true
                    use_regions_profiling=true
                    ;;

                *)
                    echo "$0: unknown grade component \`$grade_piece'" 1>&2
                    exit 1
                    ;;
            esac
        done
        ;;

    -s*)
        grade="` expr $1 : '-s\(.*\)' `"
        # just insert it as `--grade $grade' and then reparse it
        shift
        case $# in
            0)
                set - x --grade "$grade"
                ;;
            *)
                set - x --grade "$grade" "$@"
                ;;
        esac
        ;;


        --)
            shift
            break
            ;;

        *)
            break
            ;;
    esac
    shift
done

if test -r .mgnuc_opts
then
    for opt in `cat .mgnuc_opts`
    do
        case "${opt}" in

#---------------------------------------------------------------------------#
# vim: ts=4 sw=4 expandtab ft=sh
#---------------------------------------------------------------------------#
# Copyright (C) 2005 The University of Melbourne.
# This file may only be copied under the terms of the GNU General
# Public License - see the file COPYING in the Mercury distribution.
#---------------------------------------------------------------------------#
#
# mgnuc_file_opts.sh-subr:
#
# An `sh' subroutine for processing the mgnuc options that can be set from
# .mgnuc_opts files. It is included twice in mgnuc. Its implementation is
# bound tightly to the code of mgnuc.in; all the variables it manipulates
# come from there.
#
# At the moment, this includes only options that do not have arguments.
# This is because processing options with arguments is hard to do without
# overriding the argument vector, and there is no simple way to preserve
# the exact structure of the original argument vector *including* any spaces
# inside individual arguments. There is no real need (at least right now)
# for putting such options into .mgnuc_opts files.
#
#---------------------------------------------------------------------------#

        -v|--verbose)
            verbose=true
            ;;
        -v-|--no-verbose)
            verbose=false
            ;;

        --no-ansi)
            ANSI_OPTS=
            ;;

        --no-check)
            CHECK_OPTS=
            ;;

        --inline-alloc)
            INLINE_ALLOC_OPTS="-DMR_INLINE_ALLOC -DSILENT"
            ;;
        --no-inline-alloc)
            INLINE_ALLOC_OPTS=""
            ;;

        -g|--c-debug)
            c_debug=true
            ;;
        -g-|--no-c-debug)
            c_debug=false
            ;;

        --c-optimize)
            c_optimize=true
            ;;
        --no-c-optimize)
            c_optimize=false
            ;;

        --low-level-debug)
            low_level_debug=true
            ;;
        --no-low-level-debug)
            low_level_debug=false
            ;;

        --use-activation-counts)
            use_activation_counts=true
            ;;
        --no-use-activation-counts)
            use_activation_counts=false
            ;;

        --preserve-tail-recursion)
            preserve_tail_recursion=true
            ;;
        --no-preserve-tail-recursion)
            preserve_tail_recursion=false
            ;;

        --no-mercury-standard-library-directory|--no-mercury-stdlib-dir)
            unset mercury_stdlib_dir
            unset mercury_config_dir
            ;;

        --no-filter-cc)
            do_filter_cc=false
            ;;

        --halt-at-warn-if-possible)
            halt_at_warn_if_possible=true
            ;;

            *)
                echo "unknown option ${opt} in .mgnuc_opts"
                exit 1
                ;;
        esac
    done
fi

# include the file `final_grade_options.sh-subr'
#---------------------------------------------------------------------------#
# vim: ts=4 sw=4 expandtab ft=sh
#---------------------------------------------------------------------------#
# Copyright (C) 1998-2002, 2004-2007, 2009-2010 The University of Melbourne.
# Copyright (C) 2013, 2015-2016, 2020 The Mercury team.
# This file may only be copied under the terms of the GNU General
# Public License - see the file COPYING in the Mercury distribution.
#---------------------------------------------------------------------------#
#
# final_grade_options.sh-subr:
#   An `sh' subroutine for handling implications between grade-related
#   options. Used by the `ml', `mgnuc' and `c2init' scripts.
#
#   The code here should be inserted after a script's option-parsing loop.
#
# IMPORTANT: any changes to the handling of grades here may also require
# changes to compiler/handle_options.m.
#
# This file should only use the shell variables initialized by
# init_grade_options.sh-subr.
#
#---------------------------------------------------------------------------#

use_minimal_model=false
case ${use_minimal_model_stack_copy} in
    true)
        use_minimal_model=true
        ;;
esac
case ${use_minimal_model_own_stacks} in
    true)
        use_minimal_model=true
        ;;
esac

# .tr grade is not compatible with .*mm*
#   (see comment in runtime/mercury_tabling.c for rationale)
case ${use_trail},${use_minimal_model} in
    true,true)
        echo "trailing and minimal model tabling are not compatible" 1>&2
        exit 1
        ;;
esac

# .par grade is not compatible with .*mm*
#   (see comment in runtime/mercury_grade.h for rationale)
case ${use_trail},${use_minimal_model} in
    true,true)
        echo "parallel execution and minimal model tabling are not compatible" 1>&2
        exit 1
        ;;
esac

# .exts grade is not compatible with .stseg
#   (they are alternative ways of doing the same thing)
case ${extend_stacks},${stack_segments} in
    true,true)
        echo "--extend-stacks-when-needed and --stack-segments are not compatible" 1>&2
        exit 1
        ;;
esac

# stack segments are not compatible with high-level code
case $highlevel_code,$stack_segments in true,true)
    echo "--high-level-code and --stack-segments are not compatible" 1>&2
    exit 1 ;;
esac

# .debug grades are not compatible with high-level code
case ${highlevel_code},${debug} in
    true,true)
        echo "--high-level-code and --debug are not compatible" 1>&2
        exit 1
        ;;
esac

# .decldebug grades are not compatible with high-level code
case ${highlevel_code},${decl_debug} in
    true,true)
        echo "--high-level-code and --decl-debug are not compatible" 1>&2
        exit 1
        ;;
esac

# .profdeep grades are not compatible with high-level code
case ${highlevel_code},${profile_deep} in
    true,true)
        echo "--high-level-code and --deep-profiling are not compatible" 1>&2
        exit 1
        ;;
esac

# The non-C backends do not support single-precision floats, time profiling,
# memory profiling or deep profiling.
case ${target} in
    csharp|java)
        case ${single_prec_float} in
            true)
                echo "--single-prec-float and --target $target are not compatible" 1>&2
                exit 1
                ;;
        esac
        case ${profile_time} in
            true)
                echo "--profile-time and --target $target are not compatible" 1>&2
                exit 1
                ;;
        esac
        case ${profile_memory} in
            true)
                echo "--profile-memory and --target $target are not compatible" 1>&2
                exit 1
                ;;
        esac
        case ${profile_deep} in
            true)
                echo "--profile-deep and --target $target are not compatible" 1>&2
                exit 1
                ;;
        esac
        ;;
esac

# --decl-debug implies --debug
case ${decl_debug} in
    true)
        debug=true
        ;;
esac

# --target C#, Java implies --high-level-code
case ${target} in
    csharp|java)
        highlevel_code=true
        ;;
esac

# --target C#, Java implies --gc automatic.
# NOTE: the .par grade component is meaningless for the non-C backends,
# so we set it to false if they are being used.  This avoids having to
# deal with grades like "java.par".
case ${target} in
    csharp|java)
        gc_method=automatic
        thread_safe=false
        ;;
esac

# --high-level-code disables the use of low-level gcc extensions
case ${highlevel_code} in
    true)
        non_local_gotos=false
        asm_labels=false
        global_regs=false
        ;;
esac

# --use-regions-debug and --use-regions-profiling aren't meaningful
# without --use-regions
case ${use_regions} in
    false)
        use_regions_debug=false
        use_regions_profiling=false
        ;;
esac

# threadscope doesn't make sense in non-parallel grades.
case ${thread_safe} in
    false)
        threadscope=false
        ;;
esac

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

# compute the canonical grade name from the options settings
#

# include the file `canonical_grade.sh-subr'
#---------------------------------------------------------------------------#
# vim: ts=4 sw=4 expandtab ft=sh
#---------------------------------------------------------------------------#
# Copyright (C) 2000-2007, 2010 The University of Melbourne.
# Copyright (C) 2013-2017, 2020 The Mercury team.
# This file may only be copied under the terms of the GNU General
# Public License - see the file COPYING in the Mercury distribution.
#---------------------------------------------------------------------------#
#
# canonical_grade.sh-subr:
#
# An `sh' subroutine for computing a canonical grade string based on
# the values of grade-related options.
# It is used by the `ml', `c2init' and `canonical_grade' scripts.
#
# The code here should be inserted after init_grade_options.sh-subr,
# parse_grade_options.sh-subr and final_grade_options.sh-subr, which
# together define a set of shell variables giving the values of the
# various grade options.
#
# Canonical_grade.sh-subr defines the variable GRADE, which will contain
# the canonical string for the grade implied by the option values.
#
# If the option values are inconsistent, this script fragment will print
# an error message and exit with failure.
#
# IMPORTANT: any changes to the handling of grades here may also require
# changes to all the files indicated by runtime/mercury_grade.h.

case ${highlevel_code},${target} in
    true,*)
        case ${target} in
            c)
                GRADE="hlc"
                ;;
            csharp)
                GRADE="csharp"
                ;;
            java)
                GRADE="java"
                ;;
            *)
                progname=`basename $0`
                echo "${progname}: unknown target: ${target}"
                exit 1
                ;;
        esac

        case ${non_local_gotos} in
            true)
                echo "${progname}: error: nonlocal gotos are not compatible" 1>&2
                echo "${progname}: with \'--high-level-code'" 1>&2
                exit 1
                ;;
        esac

        case ${global_regs} in
            true)
                echo "${progname}: error: use of global registers is not compatible" 1>&2
                echo "${progname}: with \'--high-level-code'" 1>&2
                exit 1
                ;;
        esac

        case ${asm_labels} in
            true)
                echo "${progname}: error: use of asm labels is not compatible" 1>&2
                echo "${progname}: with \'--high-level-code'" 1>&2
                exit 1
                ;;
        esac
        ;;
    false,*)
        case ${target} in
            c)
                ;;
            *)
                echo "${progname}: error: \`--no-high-level-code' is not compatible" 1>&2
                echo "${progname}: with any target language except C" 1>&2
                exit 1
        esac

        case ${non_local_gotos},${global_regs} in
            true,true)      GRADE="fast" ;;
            true,false)     GRADE="jump" ;;
            false,true)     GRADE="reg"  ;;
            false,false)    GRADE="none" ;;
        esac

        case ${asm_labels} in
            true)       GRADE="asm_${GRADE}" ;;
            false)      ;;
        esac
        ;;
    *)
        echo "${progname}: internal error: \`--high-level-code' is not set" 1>&2
        exit 1
        ;;
esac

case ${thread_safe},${threadscope} in
    true,false)
        GRADE="${GRADE}.par"
        ;;
    true,true)
        GRADE="${GRADE}.par.threadscope"
        ;;
    false,false)
        ;;
    *)
        echo "${progname}: error: The 'threadscope' grade component may only be" 1>&2
        echo "${progname}: error: used in parallel grades"
        exit 1
        ;;
esac

case ${gc_method} in
    conservative)   GRADE="${GRADE}.gc"  ;;     # deprecated; alias for boehm
    boehm)          GRADE="${GRADE}.gc"  ;;
    boehm_debug)    GRADE="${GRADE}.gcd" ;;
    hgc)            GRADE="${GRADE}.hgc" ;;
    accurate)       GRADE="${GRADE}.agc" ;;
esac

case ${profile_time},${profile_calls},${profile_memory},${profile_deep} in
    true,true,false,false)
        GRADE="${GRADE}.prof"
        ;;
    true,false,false,false)
        GRADE="${GRADE}.proftime"
        ;;
    false,true,false,false)
        GRADE="${GRADE}.profcalls"
        ;;
    true,true,true,false)
        GRADE="${GRADE}.profall"
        ;;
    false,true,true,false)
        GRADE="${GRADE}.memprof"
        ;;
    false,false,false,true)
        GRADE="${GRADE}.profdeep"
        ;;
    false,false,false,false)
        ;;
    *)
        progname=`basename $0`
        echo "${progname}: error: invalid combination of profiling options." 1>&2
        exit 1
        ;;
esac

case ${record_term_sizes_as_words},${record_term_sizes_as_cells} in
    true,false)
        GRADE="${GRADE}.tsw"
        ;;
    false,true)
        GRADE="${GRADE}.tsc"
        ;;
    false,false)
        ;;
    *)
        progname=`basename $0`
        echo "${progname}: error: invalid combination of term size profiling options." 1>&2
        exit 1
        ;;
esac

case ${use_trail} in
    true)
        GRADE="${GRADE}.tr" ;;
    *)
        ;;
esac

case ${use_minimal_model_stack_copy},${use_minimal_model_own_stacks},${minimal_model_debug} in
    true,false,false)
        GRADE="${GRADE}.mmsc"
        ;;
    true,false,true)
        GRADE="${GRADE}.dmmsc"
        ;;
    false,true,false)
        GRADE="${GRADE}.mmos"
        ;;
    false,true,true)
        GRADE="${GRADE}.dmmos"
        ;;
    *)
        ;;
esac

case ${pregenerated_dist},${single_prec_float} in
    true,false)
        GRADE="${GRADE}.pregen"
        ;;
    false,true)
        GRADE="${GRADE}.spf"
        ;;
    false,false)
        ;;
    *)
        progname=`basename $0`
        echo "${progname}: error: pregenerated dist incompatible with single-prec float." 1>&2
        exit 1
        ;;
esac

case ${debug},${decl_debug},${ss_debug} in
    true,true,false)
        GRADE="${GRADE}.decldebug"
        ;;
    true,false,false)
        GRADE="${GRADE}.debug"
        ;;
    false,false,true)
        GRADE="${GRADE}.ssdebug"
        ;;
    false,false,false)
        ;;
    *)
        progname=`basename $0`
        echo "${progname}: error: invalid combination of debugging options." 1>&2
        exit 1
        ;;
esac

case ${ll_debug} in
    true)
        GRADE="${GRADE}.ll_debug"
        ;;
    *)
        ;;
esac;

case ${extend_stacks},${stack_segments} in
    true,false)
        GRADE="${GRADE}.exts"
        ;;
    false,true)
        GRADE="${GRADE}.stseg"
        ;;
    false,false)
        ;;
    *)
        progname=`basename $0`
        echo "${progname}: error: invalid combination of stack extension options." 1>&2
        exit 1
        ;;
esac

case ${use_regions} in
    true)
        case ${use_regions_debug},${use_regions_profiling} in
            false,false)    GRADE="${GRADE}.rbmm"   ;;
            false,true)     GRADE="${GRADE}.rbmmp"  ;;
            true,false)     GRADE="${GRADE}.rbmmd"  ;;
            true,true)      GRADE="${GRADE}.rbmmdp" ;;
        esac
        ;;
    false)
        ;;
esac

case "${mercury_stdlib_dir}" in
    "")
        MERC_ALL_C_INCL_DIRS=
        ;;
    *)
        # The option setting code above guarantees that if
        # `--mercury-stdlib-dir' is set, `--mercury-config-dir'
        # is also set.
        MERC_ALL_C_INCL_DIRS="-I${mercury_config_dir}/conf -I${mercury_stdlib_dir}/inc -I${mercury_stdlib_dir}/lib/${GRADE}/inc"
        ;;
esac

# add /usr/local/include to the default search path, if needed
ALL_LOCAL_C_INCL_DIRS=${MERCURY_ALL_LOCAL_C_INCL_DIRS=}

# Convert non-grade mgnuc options into gcc options.
#
# IMPORTANT: any changes here will require similar changes to
# compiler/compile_target_code.m.

case ${c_debug} in
    true)       C_DEBUG_OPTS="${DEBUG_OPTS}" ;;
    false)      C_DEBUG_OPTS="" ;;
esac

case ${c_optimize} in
    true)       ;;
    false)      OPT_OPTS="" ;;
esac

case ${low_level_debug} in
    true)       LLDEBUG_OPTS="-DMR_LOWLEVEL_DEBUG" ;;
    false)      LLDEBUG_OPTS="" ;;
esac

#
# convert grade mgnuc options into gcc options
#
# IMPORTANT: any changes here may require similar changes to all the files
# mentioned in runtime/mercury_grade.h.
#

HALT_AT_WARN_OPT=""
case ${highlevel_code} in
    true)
        HLC_OPTS="-DMR_HIGHLEVEL_CODE"
        case ${halt_at_warn_if_possible} in
            true)
                HALT_AT_WARN_OPT="${COMPILER_HALT_AT_WARN_OPT}"
                ;;
        esac
        ;;
    false)
        HLC_OPTS=""
        ;;
esac

case ${asm_labels} in
    true)       ASM_OPTS="-DMR_USE_ASM_LABELS" ;;
    false)      ASM_OPTS="" ;;
esac

case ${non_local_gotos} in
    true)       GOTO_OPTS="-DMR_USE_GCC_NONLOCAL_GOTOS" ;;
    false)      GOTO_OPTS="" ;;
esac

case ${global_regs} in
    true)       REG_OPTS="-DMR_USE_GCC_GLOBAL_REGISTERS" ;;
    false)      REG_OPTS="" ;;
esac

case ${thread_safe} in
    true)
        THREAD_OPTS="-DMR_THREAD_SAFE ${CFLAGS_FOR_THREADS}"
        case ${FULLARCH} in
            *linux*)
                # Don't use -ansi under Linux or we get parse errors
                # at sigset_t in the pthreads headers. This doesn't seem
                # to be necessary for recent versions of Linux/glibc
                # (e.g. glibc 2.1.2), but I've left it in so we can remain
                # compatible with older versions.
                ANSI_OPTS=""
        esac
        ;;
    false)
        THREAD_OPTS=""
        ;;
esac

case ${threadscope} in
    true)       THREADSCOPE_OPTS="-DMR_THREADSCOPE" ;;
    false)      THREADSCOPE_OPTS="" ;;
esac

# Set the correct flags if we're to use the MS Visual C runtime.
use_msvcrt=no
if test ${use_msvcrt} = "yes"; then
    case ${thread_safe} in
        # -MD states that we will use the MSVC runtime, the boehm_gc collector
        # assumes that the collector has been built as a DLL if we are using
        # the MSVC runtime so we need to define GC_NOT_DLL when the collector
        # isn't built as a DLL.
        true)   MSVCRT_OPTS="-MD" ;;
        false)  MSVCRT_OPTS="-DGC_NOT_DLL -MD" ;;
    esac
else
    MSVCRT_OPTS=""
fi

boehm_opts="-DMR_CONSERVATIVE_GC -DMR_BOEHM_GC "
case ${gc_method} in
    accurate)       GC_OPTS="-DMR_NATIVE_GC" ;;
    boehm)          GC_OPTS="${boehm_opts}" ;;
    boehm_debug)    GC_OPTS="${boehm_opts} -DMR_BOEHM_GC_DEBUG -DGC_DEBUG -DKEEP_BACK_PTRS" ;;
    hgc)            GC_OPTS="-DMR_CONSERVATIVE_GC -DMR_HGC" ;;
    conservative)   GC_OPTS="-DMR_CONSERVATIVE_GC -DMR_BOEHM_GC" ;;
    none)           GC_OPTS="" ;;
esac

case ${profile_time} in
    true)       PROF_TIME_OPTS="-DMR_MPROF_PROFILE_TIME" ;;
    false)      PROF_TIME_OPTS="" ;;
esac

case ${profile_calls} in
    true)       PROF_CALLS_OPTS="-DMR_MPROF_PROFILE_CALLS" ;;
    false)      PROF_CALLS_OPTS="" ;;
esac

case ${profile_memory} in
    true)       PROF_MEMORY_OPTS="-DMR_MPROF_PROFILE_MEMORY" ;;
    false)      PROF_MEMORY_OPTS="" ;;
esac

case ${use_activation_counts} in
    true)       ACTIVATION_COUNT_OPT="-DMR_USE_ACTIVATION_COUNTS" ;;
    false)      ACTIVATION_COUNT_OPT="";;
esac

case ${preserve_tail_recursion} in
    true)       PRESERVE_TAIL_RECURSION_OPT="-DMR_DEEP_PROFILING_TAIL_RECURSION" ;;
    false)      PRESERVE_TAIL_RECURSION_OPT="";;
esac

case ${profile_deep} in
    true)       PROF_DEEP_OPTS="-DMR_DEEP_PROFILING ${ACTIVATION_COUNT_OPT} ${PRESERVE_TAIL_RECURSION_OPT}" ;;
    false)      PROF_DEEP_OPTS="" ;;
esac

case ${record_term_sizes_as_words},${record_term_sizes_as_cells} in
    true,true)
        progname=`basename $0`
        echo "${progname}: we can't record both cell and word sizes"
        exit 1
        ;;
    true,false)
        RECORD_TERM_SIZE_OPTS="-DMR_RECORD_TERM_SIZES" ;;
    false,true)
        RECORD_TERM_SIZE_OPTS="-DMR_RECORD_TERM_SIZES -DMR_RECORD_TERM_SIZES_AS_CELLS" ;;
    false,false)
        RECORD_TERM_SIZE_OPTS="" ;;
esac

case ${use_trail} in
    true)
        TRAIL_OPTS="-DMR_USE_TRAIL"
        # See the comment in compile_c_file/7 in compiler/compile_target_code.m
        # for an explanation of this.
        case ${COMPILER} in
            gcc)    FN_ALIGN_OPTS="-falign-functions=${BYTES_PER_WORD}" ;;
            *)      FN_ALIGN_OPTS="" ;;
        esac
        ;;
    false)
        TRAIL_OPTS=""
        ;;
esac

case ${use_minimal_model_stack_copy},${use_minimal_model_own_stacks} in
    true,true)
        progname=`basename $0`
        echo "${progname}: can't enable both forms of minimal model tabling at once"
        exit 1
        ;;
    true,false)
        MINIMAL_MODEL_OPTS="-DMR_USE_MINIMAL_MODEL_STACK_COPY"
        ;;
    false,true)
        MINIMAL_MODEL_OPTS="-DMR_USE_MINIMAL_MODEL_OWN_STACKS"
        ;;
    false,false)
        MINIMAL_MODEL_OPTS=""
        ;;
esac

case ${use_minimal_model},${minimal_model_debug} in
    true,false)     ;; # MINIMAL_MODEL_OPTS is already set
    true,true)      MINIMAL_MODEL_OPTS="${MINIMAL_MODEL_OPTS} -DMR_MINIMAL_MODEL_DEBUG" ;;
    *)              MINIMAL_MODEL_OPTS="" ;;
esac

case ${pregenerated_dist},${single_prec_float} in
    true,true)
        progname=`basename $0`
        echo "${progname}: cannot enable both pregenerated dist and single-prec float"
        exit 1
        ;;
    true,false)
        PREGEN_SPF_OPTS="-DMR_PREGENERATED_DIST"
        ;;
    false,true)
        PREGEN_SPF_OPTS="-DMR_USE_SINGLE_PREC_FLOAT"
        ;;
    false,false)
        PREGEN_SPF_OPTS=""
        ;;
esac

case ${debug} in
    true)           TRACE_OPTS="-DMR_EXEC_TRACE" ;;
    false)          TRACE_OPTS="" ;;
esac

case ${decl_debug} in
    true)           DECL_DEBUG_OPTS="-DMR_DECL_DEBUG" ;;
    false)          DECL_DEBUG_OPTS="" ;;
esac

case ${ss_debug} in
    true)           SS_DEBUG_OPTS="-DMR_SS_DEBUG" ;;
    false)          SS_DEBUG_OPTS="" ;;
esac

case ${ll_debug} in
    true)           LL_DEBUG_OPTS="-DMR_LL_DEBUG ${DEBUG_OPTS} ${DISABLE_OPTS_OPT}" ;;
    false)          LL_DEBUG_OPTS="" ;;
esac

case ${extend_stacks} in
    true)           EXTEND_STACKS_OPTS="-DMR_EXTEND_STACKS_WHEN_NEEDED" ;;
    false)          EXTEND_STACKS_OPTS="" ;;
esac

case ${stack_segments} in
    true)           STACK_SEGMENTS_OPTS="-DMR_STACK_SEGMENTS" ;;
    false)          STACK_SEGMENTS_OPTS="" ;;
esac

case ${use_regions} in
    true)
        REGION_OPTS_0="-DMR_USE_REGIONS"
        case ${use_regions_debug} in
            true)   REGION_OPTS_1="${REGION_OPTS_0} -DMR_RBMM_DEBUG" ;;
            false)  REGION_OPTS_1="${REGION_OPTS_0}" ;;
        esac
        case ${use_regions_profiling} in
            true)   REGION_OPTS="${REGION_OPTS_1} -DMR_RBMM_PROFILING" ;;
            false)  REGION_OPTS="${REGION_OPTS_1}" ;;
        esac
        ;;
    false)
        REGION_OPTS=""
        ;;
esac

GCC_OPTS="${ASM_OPTS} ${GOTO_OPTS} ${REG_OPTS}"

# check that special grades are only used with gcc
case ${COMPILER} in
    gcc|unknown)
        ;;
    *)  case "${GCC_OPTS}" in
            *USE_GCC*)
                progname=`basename $0`
                echo "${progname}: For compilers other than GNU C, the only" 1>&2
                echo "${progname}: base grade allowed is \`none'" 1>&2
                ;;
        esac
        ;;
esac

# if we're using global registers, add CFLAGS_FOR_REGS
case ${global_regs} in
    true)       GCC_OPTS="${GCC_OPTS} ${CFLAGS_FOR_REGS}" ;;
    false)      ;;
esac

# if we're using non-local gotos, add CFLAGS_FOR_GOTOS
case ${non_local_gotos} in
    true)       GCC_OPTS="${GCC_OPTS} ${CFLAGS_FOR_GOTOS}" ;;
    false)      ;;
esac

# if sanitizers were enabled at configure time, add CFLAGS_FOR_SANITIZERS
SANITIZER_OPTS="${CFLAGS_FOR_SANITIZERS}"

# Use any applicable LTO options
LTO_OPTS="${CFLAGS_FOR_LTO}"

#
# Special case hacks for particular architectures
# Any code here needs to be duplicated in ../configure.ac.
#

ARCH_OPTS=""

# XXX gcc generates warnings about possibly uninitialized variables in
# high-level C code. clang would, too, if we did not suppress all warnings.
case "${COMPILER},${highlevel_code}" in
    gcc,true)
        CHECK_OPTS="${CHECK_OPTS} -Wno-uninitialized"
        ;;
esac

case "${FULLARCH}" in
    i*86-*|x86_64*)
        # The use of stack_pointer in the ASM_JUMP macro defined in
        # runtime/mercury_goto.h causes lots of warnings about using possibly
        # uninitialized variables; there's no easy way to suppress them except
        # by disabling the warning.
        case "${COMPILER},${highlevel_code}" in
            gcc,false)
                CHECK_OPTS="${CHECK_OPTS} -Wno-uninitialized"
                ;;
        esac
        ;;
    *-solaris*|*-sunos*)
        # The solaris headers for pthreads are not ANSI :-(
        case ${thread_safe} in
            true)
                ANSI_OPTS=""
                ;;
        esac
        ;;
esac

# gcc versions 9, 10 and 11 replace calls to strcmp and related functions with
# specialised code when some of the arguments are string constants.
# The above versions of gcc emit spurious warnings about the code they
# introduce when -Warray-bounds is enabled.
# 
case "${C_COMPILER_TYPE}" in
    gcc_9_*|gcc_1[0-9]_*)
        CHECK_OPTS="${CHECK_OPTS} -Wno-array-bounds"
    ;;
esac

case ${COMPILER} in gcc)
    case "${FULLARCH}" in
        i*86*)
            case "$*" in
            # Workarounds for internal problems with GCC in asm_fast.gc
            # on i*86. Reported against gcc 4.4.5 and 4.6.0.
            *" ml_backend.ml_closure_gen.c "*)
                ARCH_OPTS="${ARCH_OPTS} -O0"
                ;;
            *" ml_backend.ml_unify_gen.c "*)
                ARCH_OPTS="${ARCH_OPTS} -O0"
                ;;
            *" ml_backend.rtti_to_mlds.c "*)
                ARCH_OPTS="${ARCH_OPTS} -O0"
                ;;
            *" display_report.c "*)
                ARCH_OPTS="${ARCH_OPTS} -O0"
                ;;
            # Workaround for a internal compiler error with GCC 4.8
            # in grades that use global registers.
            *" mercury_ho_call.c "*)
                case ${global_regs} in true)
                    ARCH_OPTS="${ARCH_OPTS} -O0"
                    ;;
                esac
                ;;
            esac
            ;;
    esac
    ;;
esac

# On sparc-sun-solaris2, we need to use -fPIC rather than -fpic
# because otherwise the Mercury standard library overflows the fixed limit
# on the number of "small pic" references.
# Similarly, on sparc64 OpenBSD, no grades fit into the 13-bit GOT.

case "${FULLARCH}" in
    sparc-sun-solaris2*|sparc64*-openbsd*)
        case "$*" in
            *-fpic*)
                echo "mgnuc: using -fPIC rather than -fpic"
                OVERRIDE_OPTS="${OVERRIDE_OPTS} -fPIC"
                ;;
        esac
        ;;
esac

# Using global register variables triggers an internal error in the LRA pass of
# GCC 9.1 and 9.2 on x86_64 systems in debug grades unless we compile at -O0.
# See: <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91430>
#
# Changes to this need to be reflected in the predicate
# gather_c_compiler_flags/3 in compiler/compile_target_code.m.

case "${FULLARCH}" in x86_64*)
    case ${global_regs},${debug} in
        true,true)
            case "${C_COMPILER_TYPE}" in
                gcc_9_*)
                    ARCH_OPTS="${ARCH_OPTS} -O0"
                    ;;
            esac
            ;;
    esac
    ;;
esac

# At -O2 compilation times on Mac OS X are extremely slow for
# Apple GCC 4.{0,2}. We must force GCC to use -O0 here in order
# to get acceptable compilation times.
# Changes to this need to be reflected in the predicate 
# gather_c_compiler_flags/3 in compiler/compile_target_code.m.

case ${FULLARCH} in
    *apple*darwin*)
        case ${debug} in
            true)
                case ${COMPILER} in
                    gcc)
                        OVERRIDE_OPTS="${OVERRIDE_OPTS} -O0"
                        ;;
                esac
                ;;
        esac
        ;;
esac

if test -r .mgnuc_copts
then
    INVISIBLE_OPTS=`cat .mgnuc_copts`
else
    INVISIBLE_OPTS=""
fi

FILTERCC=""
case ${asm_labels},${do_filter_cc} in
    true,true)
        # Check if mfiltercc is available as we may be bootstrapping with
        # an older compiler which did not have it.
        if test -n "${MKTEMP}" && mfiltercc </dev/null 2>/dev/null
        then
            FILTERCC="mfiltercc"
        fi
    ;;
esac

ALL_CC_OPTS="${MERC_ALL_C_INCL_DIRS}\
    ${ANSI_OPTS}\
    ${CHECK_OPTS}\
    ${OPT_OPTS}\
    ${LTO_OPTS}\
    ${HLC_OPTS}\
    ${GCC_OPTS}\
    ${HALT_AT_WARN_OPT}\
    ${MSVCRT_OPTS}\
    ${GC_OPTS}\
    ${DEFINE_OPTS}\
    ${STACK_TRACE_OPTS}\
    ${TRACE_OPTS}\
    ${DECL_DEBUG_OPTS}\
    ${SS_DEBUG_OPTS}\
    ${LL_DEBUG_OPTS}\
    ${EXTEND_STACKS_OPTS}\
    ${STACK_SEGMENTS_OPTS}\
    ${LLDEBUG_OPTS}\
    ${C_DEBUG_OPTS}\
    ${PROF_TIME_OPTS}\
    ${PROF_CALLS_OPTS}\
    ${PROF_MEMORY_OPTS}\
    ${PROF_DEEP_OPTS}\
    ${INLINE_ALLOC_OPTS}\
    ${TRAIL_OPTS}\
    ${RECORD_TERM_SIZE_OPTS}\
    ${MINIMAL_MODEL_OPTS}\
    ${PREGEN_SPF_OPTS}\
    ${SANITIZER_OPTS}\
    ${SPLIT_OPTS}\
    ${THREAD_OPTS}\
    ${THREADSCOPE_OPTS}\
    ${REGION_OPTS}\
    ${ARCH_OPTS}\
    ${FN_ALIGN_OPTS}\
    ${INVISIBLE_OPTS}"

case $# in
    0)
        set ${CC} ${ALL_CC_OPTS} ${OVERRIDE_OPTS}
        ;;
    *)
        set ${CC} ${ALL_CC_OPTS} "$@" ${OVERRIDE_OPTS} ${ALL_LOCAL_C_INCL_DIRS}
        ;;
esac

case ${verbose} in
    true)
        echo "$@"
        ;;
esac

if test -z "${FILTERCC}"
then
    exec "$@"
fi

# mktemp should give its own error message.
tmp=`${MKTEMP} ${TMPDIR}/mgnuc.XXXXXX` || exit 1
trap 'status=$?; rm -f ${tmp}; exit ${status}' 0 1 2 3 13 15
"$@" 2> ${tmp}
status=$?
"${FILTERCC}" < ${tmp} >&2
exit ${status}
