Files
mercury/runtime/mercury_grade.h
Zoltan Somogyi ada627928c Stop supporting --tags none for C.
The effect of --tags none is to tell the compiler not to use any primary
tag bits. The option is not needed when targeting Java, C# or Erlang,
since with these languages we can't use primary tags. It was effective
only in C grades. However, since using primary tags is always faster,
the only use case for --tags none was to measure *how much* faster.
This was useful in Mercury's early development, but has become obsolete
ages ago.

compiler/options.m:
doc/user_guide.texi:
    Delete the --tags option. For non-C targets, it was never needed,
    and with the deletion of first --tags high and now --tags none,
    --tags low is the only supported value for C.

    Change the documentation of the --num-ptag-bits option to emphasize
    that name, not its older but less specific synonym, --num-tag-bits.
    Document that the only reason to use this option is cross-compilation.

    In user_guide.texi, also delete some references to long-deleted
    options for reserved addresses and objects, and some duplicate lines
    in comments.

NEWS:
    Document the option removal.

compiler/globals.m:
    Delete the tags_method field of the globals, since it is not
    needed anymore.

compiler/handle_options.m:
    Delete the code that converts the value of the --tags option to the
    value of the tags_method field of the globals.

    Ensure that the value of the num_ptag_bits option is (a) zero when
    not targeting C, and (b) either 2 or 3 when targeting C.

compiler/du_type_layout.m:
    Check that we are using 2 or 3 ptag bits when targeting C.

compiler/const_struct.m:
    Conform to the changes above.

runtime/mercury_grade.h:
    Generate an error if MR_TAGBITS is zero (which could happen
    only with --tags none).

runtime/mercury_tags.h:
    Delete the definitions of the list access macros for the MR_TAGBITS == 0
    case.
2020-04-28 13:36:58 +10:00

511 lines
21 KiB
C

// vim: ts=4 sw=4 expandtab ft=c
// Copyright (C) 1997-2012 The University of Melbourne.
// Copyright (C) 2013-2014, 2016-2018 The Mercury team.
// This file is distributed under the terms specified in COPYING.LIB.
// The main purpose of this file is to define the MR_GRADE_VAR macro,
// which we use to get the linker to generate an error if the object files
// linked into an executable were compiled with inconsistent grades.
//
// We do this by (a) having mercury_grade.c define a variable whose name
// is MR_GRADE_VAR; and (b) having all .c files generated by the Mercury
// compiler include a reference to the variable whose name is MR_GRADE_VAR.
// The latter will succeed only if the value of the MR_GRADE_VAR macro
// in that object file is the same as its value during the compilation
// of mercury_grade.c.
//
// The value of MR_GRADE_VAR is the link-check version of the Mercury grade.
// This file also computes the user-visible version of the grade into
// the macro MR_GRADE_OPT. This user-visible version of the grade
//
// - uses dots instead of underscores to separate grade components;
// - omits grade components that are the result of autoconfiguration and are
// of no interest to users, such as _tags2; and
// - omits version numbers from the grade components that have them.
//
// Any conditional compilation macros that affect link compatibility
// should be included here. For documentation on the meaning of these macros,
// see runtime/mercury_conf_param.h.
//
// There are many constraints that apply to grade components. The ones
// that apply between two or more grade components are enforced here,
// with one exception noted below, which is enforced in mercury.h.
// The constraints that also involve macros that do *not* represent
// grade components (such as MR_CLANG) are enforced in mercury_conf_param.h.
//
// IMPORTANT: any changes here may also require changes to
// runtime/mercury_conf_param.h
// scripts/init_grade_options.sh-subr
// scripts/canonical_grade.sh-subr
// scripts/parse_grade_options.sh-subr
// scripts/final_grade_options.sh-subr
// scripts/mgnuc.in
// scripts/ml.in
// compiler/handle_options.m
// compiler/compile_target_code.m
// configure.in
#ifndef MERCURY_GRADES_H
#define MERCURY_GRADES_H
#include "mercury_std.h" // for MR_STRINGIFY and MR_PASTE2
#include "mercury_tags.h" // for MR_TAGBITS
// The following series of tests define two macros piece by piece.
//
// MR_GRADE encodes the value of all the grade options; we use it to ensure
// that all object files linked together have the same values of these options.
//
// MR_GRADE_OPT encodes the values of only the grade options that it makes
// sense to change on the compiler command line.
// Part 0 of the grade is a binary compatibility version number.
// You should increment it any time you make a change that breaks
// binary backwards compatibility.
// Note that the binary compatibility version number has no direct
// relationship with the source release number (which is in ../VERSION).
//
// It is a good idea to inspect all code for RTTI version number checks
// and remove them when increasing the binary compatibility version number.
// Searching for MR_RTTI_VERSION__ should find all code related to the
// RTTI version number.
//
// The MR_GRADE_EXEC_TRACE_VERSION_NO, MR_GRADE_DEEP_PROF_VERSION_NO and
// MR_GRADE_LLC_PAR_VERSION_NO macros should be incremented when a change
// breaks binary backwards compatibility only in debugging, deep profiling
// and low-level C parallel grades respectively.
#define MR_GRADE_PART_0 v19_
#define MR_GRADE_EXEC_TRACE_VERSION_NO 12
#define MR_GRADE_DEEP_PROF_VERSION_NO 4
#define MR_GRADE_LLC_PAR_VERSION_NO 1
#define MR_GRADE_TRAIL_VERSION_NO 1
#ifdef MR_HIGHLEVEL_CODE
#define MR_GRADE_PART_1 MR_PASTE2(MR_GRADE_PART_0, hlc)
#define MR_GRADE_OPT_PART_1 "hlc"
// Grade component 2 used to specify the use/nonuse of gcc nested functions.
// This grade component is repeated below version information.
#ifdef MR_THREAD_SAFE
#define MR_GRADE_PART_3 MR_PASTE2(MR_GRADE_PART_1, _par)
#define MR_GRADE_OPT_PART_3 MR_GRADE_OPT_PART_1 ".par"
#else
#define MR_GRADE_PART_3 MR_GRADE_PART_1
#define MR_GRADE_OPT_PART_3 MR_GRADE_OPT_PART_1
#endif
#else // ! MR_HIGHLEVEL_CODE
#ifdef MR_USE_ASM_LABELS
#define MR_GRADE_PART_1 MR_PASTE2(MR_GRADE_PART_0, asm_)
#define MR_GRADE_OPT_PART_1 "asm_"
#else
#define MR_GRADE_PART_1 MR_GRADE_PART_0
#define MR_GRADE_OPT_PART_1 ""
#endif
#ifdef MR_USE_GCC_NONLOCAL_GOTOS
#ifdef MR_USE_GCC_GLOBAL_REGISTERS
#define MR_GRADE_PART_2 MR_PASTE2(MR_GRADE_PART_1, fast)
#define MR_GRADE_OPT_PART_2 MR_GRADE_OPT_PART_1 "fast"
#else
#define MR_GRADE_PART_2 MR_PASTE2(MR_GRADE_PART_1, jump)
#define MR_GRADE_OPT_PART_2 MR_GRADE_OPT_PART_1 "jump"
#endif
#else
#ifdef MR_USE_GCC_GLOBAL_REGISTERS
#define MR_GRADE_PART_2 MR_PASTE2(MR_GRADE_PART_1, reg)
#define MR_GRADE_OPT_PART_2 MR_GRADE_OPT_PART_1 "reg"
#else
#define MR_GRADE_PART_2 MR_PASTE2(MR_GRADE_PART_1, none)
#define MR_GRADE_OPT_PART_2 MR_GRADE_OPT_PART_1 "none"
#endif
#endif
// This grade component is repeated above without the version information.
#ifdef MR_THREAD_SAFE
#define MR_GRADE_PART_3 MR_PASTE3(MR_GRADE_PART_2, _par, MR_GRADE_LLC_PAR_VERSION_NO)
#define MR_GRADE_OPT_PART_3 MR_GRADE_OPT_PART_2 ".par"
#else
#define MR_GRADE_PART_3 MR_GRADE_PART_2
#define MR_GRADE_OPT_PART_3 MR_GRADE_OPT_PART_2
#endif
#endif // ! MR_HIGHLEVEL_CODE
#if defined(MR_HGC)
#define MR_GRADE_PART_4 MR_PASTE2(MR_GRADE_PART_3, _hgc)
#define MR_GRADE_OPT_PART_4 MR_GRADE_OPT_PART_3 ".hgc"
#elif defined(MR_BOEHM_GC_DEBUG)
#define MR_GRADE_PART_4 MR_PASTE2(MR_GRADE_PART_3, _gcd)
#define MR_GRADE_OPT_PART_4 MR_GRADE_OPT_PART_3 ".gcd"
#elif defined(MR_BOEHM_GC) || defined(MR_CONSERVATIVE_GC)
#define MR_GRADE_PART_4 MR_PASTE2(MR_GRADE_PART_3, _gc)
#define MR_GRADE_OPT_PART_4 MR_GRADE_OPT_PART_3 ".gc"
#elif defined(MR_NATIVE_GC)
#define MR_GRADE_PART_4 MR_PASTE2(MR_GRADE_PART_3, _agc)
#define MR_GRADE_OPT_PART_4 MR_GRADE_OPT_PART_3 ".agc"
#else
#define MR_GRADE_PART_4 MR_GRADE_PART_3
#define MR_GRADE_OPT_PART_4 MR_GRADE_OPT_PART_3
#endif
// There is an active copy of this check in runtime/mercury.h;
// see the comment there for why it is needed.
//
// #ifdef MR_NATIVE_GC
// #ifdef MR_THREAD_SAFE
// #error "Sorry, not supported: --gc accurate --thread-safe"
// #endif
// #endif
#ifdef MR_DEEP_PROFILING
#define MR_GRADE_PART_5 MR_PASTE3(MR_GRADE_PART_4, _profdeep, MR_GRADE_DEEP_PROF_VERSION_NO)
#define MR_GRADE_OPT_PART_5 MR_GRADE_OPT_PART_4 ".profdeep"
#if defined(MR_MPROF_PROFILE_TIME) || defined(MR_MPROF_PROFILE_CALLS) \
|| defined(MR_MPROF_PROFILE_MEMORY)
// Deep profiling is completely separate from the other profiling
// alternatives, and there is no point in allowing their combination.
#error "deep profiling is incompatible with mprof-style profiling"
#endif
#ifdef MR_HIGHLEVEL_CODE
#error "deep profiling is incompatible with --high-level-code"
#endif
#else // ! MR_DEEP_PROFILING
#ifdef MR_MPROF_PROFILE_TIME
#ifdef MR_MPROF_PROFILE_CALLS
#ifdef MR_MPROF_PROFILE_MEMORY
#define MR_GRADE_PART_5 MR_PASTE2(MR_GRADE_PART_4, _profall)
#define MR_GRADE_OPT_PART_5 MR_GRADE_OPT_PART_4 ".profall"
#else // ! MR_MPROF_PROFILE_MEMORY
#define MR_GRADE_PART_5 MR_PASTE2(MR_GRADE_PART_4, _prof)
#define MR_GRADE_OPT_PART_5 MR_GRADE_OPT_PART_4 ".prof"
#endif // ! MR_MPROF_PROFILE_MEMORY
#else // ! MR_MPROF_PROFILE_CALLS
#ifdef MR_MPROF_PROFILE_MEMORY
#error "memory profiling requires call profiling"
#else // ! MR_MPROF_PROFILE_MEMORY
// Currently useless, but...
#define MR_GRADE_PART_5 MR_PASTE2(MR_GRADE_PART_4, _proftime)
#define MR_GRADE_OPT_PART_5 MR_GRADE_OPT_PART_4 ".proftime"
#endif // MR_MPROF_PROFILE_MEMORY
#endif // MR_MPROF_PROFILE_CALLS
#else // ! MR_MPROF_PROFILE_TIME
#ifdef MR_MPROF_PROFILE_CALLS
#ifdef MR_MPROF_PROFILE_MEMORY
#define MR_GRADE_PART_5 MR_PASTE2(MR_GRADE_PART_4, _memprof)
#define MR_GRADE_OPT_PART_5 MR_GRADE_OPT_PART_4 ".memprof"
#else // ! MR_MPROF_PROFILE_MEMORY
#define MR_GRADE_PART_5 MR_PASTE2(MR_GRADE_PART_4, _profcalls)
#define MR_GRADE_OPT_PART_5 MR_GRADE_OPT_PART_4 ".profcalls"
#endif // MR_MPROF_PROFILE_MEMORY
#else // ! MR_MPROF_PROFILE_CALLS
#ifdef MR_MPROF_PROFILE_MEMORY
#error "memory profiling requires call profiling"
#else // ! MR_MPROF_PROFILE_MEMORY
#define MR_GRADE_PART_5 MR_GRADE_PART_4
#define MR_GRADE_OPT_PART_5 MR_GRADE_OPT_PART_4
#endif // MR_MPROF_PROFILE_MEMORY
#endif // MR_MPROF_PROFILE_CALLS
#endif // ! MR_MPROF_PROFILE_TIME
#endif // MR_DEEP_PROFILING
#ifdef MR_RECORD_TERM_SIZES
#ifdef MR_RECORD_TERM_SIZES_AS_CELLS
#define MR_GRADE_PART_6 MR_PASTE2(MR_GRADE_PART_5, _tsc)
#define MR_GRADE_OPT_PART_6 MR_GRADE_OPT_PART_5 ".tsc"
#else
#define MR_GRADE_PART_6 MR_PASTE2(MR_GRADE_PART_5, _tsw)
#define MR_GRADE_OPT_PART_6 MR_GRADE_OPT_PART_5 ".tsw"
#endif
#ifdef MR_HIGHLEVEL_CODE
#error "term size profiling is incompatible with --high-level-code"
#endif
#else
#define MR_GRADE_PART_6 MR_GRADE_PART_5
#define MR_GRADE_OPT_PART_6 MR_GRADE_OPT_PART_5
#endif
#ifdef MR_USE_TRAIL
#ifdef MR_USE_FIXED_SIZE_TRAIL
#define MR_GRADE_PART_7 MR_PASTE3(MR_GRADE_PART_6, _trfix, MR_GRADE_TRAIL_VERSION_NO)
#else
#define MR_GRADE_PART_7 MR_PASTE3(MR_GRADE_PART_6, _trseg, MR_GRADE_TRAIL_VERSION_NO)
#endif
#define MR_GRADE_OPT_PART_7 MR_GRADE_OPT_PART_6 ".tr"
#else
#define MR_GRADE_PART_7 MR_GRADE_PART_6
#define MR_GRADE_OPT_PART_7 MR_GRADE_OPT_PART_6
#endif
// Grade component 8 used to be used for the .rt (reserve tag) grades.
// It is currently unused.
#define MR_GRADE_PART_8 MR_GRADE_PART_7
#define MR_GRADE_OPT_PART_8 MR_GRADE_OPT_PART_7
#ifdef MR_USE_MINIMAL_MODEL_STACK_COPY
#ifdef MR_USE_MINIMAL_MODEL_OWN_STACKS
#error "cannot use both forms of minimal model tabling at once"
#endif
#endif
#ifdef MR_USE_MINIMAL_MODEL_STACK_COPY
#ifdef MR_MINIMAL_MODEL_DEBUG
#define MR_GRADE_PART_9 MR_PASTE2(MR_GRADE_PART_8, _dmmsc)
#define MR_GRADE_OPT_PART_9 MR_GRADE_OPT_PART_8 ".dmmsc"
#else
#define MR_GRADE_PART_9 MR_PASTE2(MR_GRADE_PART_8, _mmsc)
#define MR_GRADE_OPT_PART_9 MR_GRADE_OPT_PART_8 ".mmsc"
#endif
#elif MR_USE_MINIMAL_MODEL_OWN_STACKS
#ifdef MR_MINIMAL_MODEL_DEBUG
#define MR_GRADE_PART_9 MR_PASTE2(MR_GRADE_PART_8, _dmmos)
#define MR_GRADE_OPT_PART_9 MR_GRADE_OPT_PART_8 ".dmmos"
#else
#define MR_GRADE_PART_9 MR_PASTE2(MR_GRADE_PART_8, _mmos)
#define MR_GRADE_OPT_PART_9 MR_GRADE_OPT_PART_8 ".mmos"
#endif
#else
#define MR_GRADE_PART_9 MR_GRADE_PART_8
#define MR_GRADE_OPT_PART_9 MR_GRADE_OPT_PART_8
#endif
#if (defined(MR_USE_MINIMAL_MODEL_STACK_COPY) || \
defined(MR_USE_MINIMAL_MODEL_OWN_STACKS))
// One implementation of minimal model tabling works by saving and restoring
// segments of the nondet stack, the other by creating a separate stack for
// each generator. Since in high level code grades we don't have a nondet
// stack that we can save and restore and we can't establish extra stacks,
// both forms of minimal model tabling are fundamentally incompatible
// with high level code.
#if defined(MR_HIGHLEVEL_CODE)
#error "high level code and minimal model tabling are not compatible"
#endif
// Neither form of the minimal model tabling works if the system recovers
// memory allocated after a choice point when backtracking to that choice
// point. This rules out the use of the native Mercury collector, as well as
// the absence of a collector. (This may change for the own stack model,
// with more work.)
#if !defined(MR_CONSERVATIVE_GC)
#error "minimal model tabling requires conservative gc"
#endif
// Native gc needs to be able to redirect pointers to the heap. Minimal model
// tabling takes snapshots of stack segments that may contain pointers to the
// heap, or creates extra stacks that may contain pointers to the heap,
// but there is currently no mechanism implemented to trace and redirect
// such pointers.
//
// XXX This test is redundant; if we use conservative (i.e. Boehm) gc,
// we cannot also use native (also known as accurate) gc.
#if defined(MR_NATIVE_GC)
#error "minimal model tabling and native gc are not compatible"
#endif
// Saving and restoring the trail state would not be sufficient
// to handle the combination of trailing and minimal model tabling.
// Consider the following sequence of events:
//
// execution enters a goal being committed across
// a new entry is pushed on the trail
// a tabled goal suspends,
// causing the saving of a trail segment
// and then a failure
// the goal being committed across fails,
// which invokes a failed commit on the trail entry
// ...
// the tabled goal is resumed,
// causing the restoring of the saved trail segment
// and then a success
// the goal being committed across now succeeds,
// which invokes a successful commit on the trail entry
//
// The trail handler will be thoroughly confused by such a sequence.
//
// Until we can figure out (and implement) a fix for this problem,
// trailing cannot be used together with either form of minimal model
// tabling.
#if defined(MR_USE_TRAIL)
#error "trailing and minimal model tabling are not compatible"
#endif
#endif
// Parts 10-11 (i.e. tag bits, and (un)boxed float) are documented as
// "not for general use", and can't be set via the `--grade' option;
// we therefore can't make them part of the grade option string.
//
// Single-precision floats do form part of the grade option string
// and they imply unboxed floats.
#if MR_TAGBITS == 0
#error "MR_TAGBITS must be greater than zero"
#else
#define MR_GRADE_PART_10 MR_PASTE2(MR_GRADE_PART_9, \
MR_PASTE2(_tags, MR_TAGBITS))
#endif
#define MR_GRADE_OPT_PART_10 MR_GRADE_OPT_PART_9
#if defined(MR_PREGENERATED_DIST)
#define MR_GRADE_PART_11 MR_PASTE2(MR_GRADE_PART_10, _pregen)
#define MR_GRADE_OPT_PART_11 MR_GRADE_OPT_PART_10 ".pregen"
#if defined(MR_USE_SINGLE_PREC_FLOAT)
#error "pregenerated code cannot use single-precision floats"
#endif
#elif defined(MR_USE_SINGLE_PREC_FLOAT)
#if defined(MR_BOXED_FLOAT)
#error "single-precision floats implies unboxed floats"
#endif
#define MR_GRADE_PART_11 MR_PASTE2(MR_GRADE_PART_10, _spf)
#define MR_GRADE_OPT_PART_11 MR_GRADE_OPT_PART_10 ".spf"
#elif defined(MR_BOXED_FLOAT)
#define MR_GRADE_PART_11 MR_GRADE_PART_10
#define MR_GRADE_OPT_PART_11 MR_GRADE_OPT_PART_10
#else // "ubf" stands for "unboxed float"
#define MR_GRADE_PART_11 MR_PASTE2(MR_GRADE_PART_10, _ubf)
#define MR_GRADE_OPT_PART_11 MR_GRADE_OPT_PART_10
#endif
// Part 12 (i.e. MR_NEW_MERCURYFILE_STRUCT) can't be set by the `--grade'
// option; it is intended to be set by the configure script at configuration
// time. We therefore don't include it in the grade option string.
#ifdef MR_NEW_MERCURYFILE_STRUCT
#define MR_GRADE_PART_12 MR_PASTE2(MR_GRADE_PART_11, _file)
#else
#define MR_GRADE_PART_12 MR_GRADE_PART_11
#endif
#define MR_GRADE_OPT_PART_12 MR_GRADE_OPT_PART_11
// Part 13 used to record the absence/presence of the .regparm grade component
// with MR_HIGHLEVEL_CODE, and the absence/presence of the .picreg grade
// component for !MR_HIGHLEVEL_CODE and MR_USE_GCC_GLOBAL_REGISTERS.
// Neither is in use anymore.
//
// The .regparm part specified an optimized calling convention of 32-bit x86
// machines, which turns out to be a pessimizing calling convention on x86/64.
//
// Once upon a time, on x86 machines with MR_USE_GCC_GLOBAL_REGISTERS,
// we reserved three global registers if we could, but had to be content
// with two if we were generating position independent code, since PIC needed
// a register for itself. However, the difference caused problems in linking
// object files compiled with different numbers of global registers reserved,
// and gcc bugs kept generating crashes with three reserved registers,
// so we now always reserve only two global registers. Therefore the
// distinction that .picreg used to record has vanished.
#define MR_GRADE_PART_13 MR_GRADE_PART_12
#define MR_GRADE_OPT_PART_13 MR_GRADE_OPT_PART_12
#if defined(MR_DECL_DEBUG)
#define MR_GRADE_PART_14 MR_PASTE3(MR_GRADE_PART_13, _decldebug, MR_GRADE_EXEC_TRACE_VERSION_NO)
#define MR_GRADE_OPT_PART_14 MR_GRADE_OPT_PART_13 ".decldebug"
#if ! defined(MR_EXEC_TRACE)
#error "declarative debugging requires execution tracing"
#endif
#else
#if defined(MR_EXEC_TRACE)
#define MR_GRADE_PART_14 MR_PASTE3(MR_GRADE_PART_13, _debug, MR_GRADE_EXEC_TRACE_VERSION_NO)
#define MR_GRADE_OPT_PART_14 MR_GRADE_OPT_PART_13 ".debug"
#else
#if defined(MR_SS_DEBUG)
#define MR_GRADE_PART_14 MR_PASTE3(MR_GRADE_PART_13, _ssdebug, MR_GRADE_EXEC_TRACE_VERSION_NO)
#define MR_GRADE_OPT_PART_14 MR_GRADE_OPT_PART_13 ".ssdebug"
#else
#define MR_GRADE_PART_14 MR_GRADE_PART_13
#define MR_GRADE_OPT_PART_14 MR_GRADE_OPT_PART_13
#endif
#endif
#endif
#if defined(MR_LL_DEBUG)
#define MR_GRADE_PART_15 MR_PASTE2(MR_GRADE_PART_14, _ll_debug)
#define MR_GRADE_OPT_PART_15 MR_GRADE_OPT_PART_14 ".ll_debug"
#else
#define MR_GRADE_PART_15 MR_GRADE_PART_14
#define MR_GRADE_OPT_PART_15 MR_GRADE_OPT_PART_14
#endif
#if defined(MR_EXTEND_STACKS_WHEN_NEEDED)
#define MR_GRADE_PART_16 MR_PASTE2(MR_GRADE_PART_15, _exts)
#define MR_GRADE_OPT_PART_16 MR_GRADE_OPT_PART_15 ".exts"
#if defined(MR_HIGHLEVEL_CODE)
#error "--extend-stacks-when-needed and --high-level-code are not compatible"
#endif
#if defined(MR_STACK_SEGMENTS)
#error "--extend-stacks-when-needed and --stack-segments are not compatible"
#endif
#elif defined(MR_STACK_SEGMENTS)
#define MR_GRADE_PART_16 MR_PASTE2(MR_GRADE_PART_15, _stseg)
#define MR_GRADE_OPT_PART_16 MR_GRADE_OPT_PART_15 ".stseg"
#if defined(MR_HIGHLEVEL_CODE)
#error "--stack-segments and --high-level-code are not compatible"
#endif
#else
#define MR_GRADE_PART_16 MR_GRADE_PART_15
#define MR_GRADE_OPT_PART_16 MR_GRADE_OPT_PART_15
#endif
#if defined(MR_USE_REGIONS)
#if defined(MR_RBMM_DEBUG)
#if defined(MR_RBMM_PROFILING)
#define MR_GRADE_PART_17 MR_PASTE2(MR_GRADE_PART_16, _rbmmdp)
#define MR_GRADE_OPT_PART_17 MR_GRADE_OPT_PART_16 ".rbmmdp"
#else
#define MR_GRADE_PART_17 MR_PASTE2(MR_GRADE_PART_16, _rbmmd)
#define MR_GRADE_OPT_PART_17 MR_GRADE_OPT_PART_16 ".rbmmd"
#endif
#else
#if defined(MR_RBMM_PROFILING)
#define MR_GRADE_PART_17 MR_PASTE2(MR_GRADE_PART_16, _rbmmp)
#define MR_GRADE_OPT_PART_17 MR_GRADE_OPT_PART_16 ".rbmmp"
#else
#define MR_GRADE_PART_17 MR_PASTE2(MR_GRADE_PART_16, _rbmm)
#define MR_GRADE_OPT_PART_17 MR_GRADE_OPT_PART_16 ".rbmm"
#endif
#endif
#else
#define MR_GRADE_PART_17 MR_GRADE_PART_16
#define MR_GRADE_OPT_PART_17 MR_GRADE_OPT_PART_16
#endif
#if defined(MR_THREADSCOPE)
#define MR_GRADE_PART_18 MR_PASTE2(MR_GRADE_PART_17, _threadscope)
#define MR_GRADE_OPT_PART_18 MR_GRADE_OPT_PART_17 ".threadscope"
#if !defined(MR_THREAD_SAFE)
#error "threadscope-style profiling may be used only with parallel grades"
#endif
#else
#define MR_GRADE_PART_18 MR_GRADE_PART_17
#define MR_GRADE_OPT_PART_18 MR_GRADE_OPT_PART_17
#endif
#if defined(MR_BOXED_INT64S)
#define MR_GRADE_PART_19 MR_GRADE_PART_18
#define MR_GRADE_OPT_PART_19 MR_GRADE_OPT_PART_18
#else // "ubi64" stands for "unboxed integers 64-bit"
#define MR_GRADE_PART_19 MR_PASTE2(MR_GRADE_PART_18, _ubi64)
#define MR_GRADE_OPT_PART_19 MR_GRADE_OPT_PART_18
#endif
#define MR_GRADE MR_GRADE_PART_19
#define MR_GRADE_OPT MR_GRADE_OPT_PART_19
#define MR_GRADE_VAR MR_PASTE2(MR_grade_,MR_GRADE)
#define MR_GRADE_STRING MR_STRINGIFY(MR_GRADE)
extern const char MR_GRADE_VAR;
#endif // MERCURY_GRADES_H