Files
mercury/runtime/mercury_overflow.h
Julien Fischer a9fbc1e528 Only define MR_nondetstack_inclusion_check in low-level C grades.
runtime/mercury_overflow.c:
	As above: compiling this function in high-level C grades
	will fail since it refers to fields of the MR_Context
	structure that do not exist in those grades.
2014-04-22 10:44:02 +10:00

146 lines
6.5 KiB
C

/*
** vim: ts=4 sw=4 expandtab
*/
/*
** Copyright (C) 1995-1998,2000-2001, 2005-2006 The University of Melbourne.
** This file may only be copied under the terms of the GNU Library General
** Public License - see the file COPYING.LIB in the Mercury distribution.
*/
/* mercury_overflow.h - definitions for overflow checks */
#ifndef MERCURY_OVERFLOW_H
#define MERCURY_OVERFLOW_H
#include "mercury_types.h"
#include "mercury_memory_zones.h"
/*
** If maxfr is not in any of the zones of the nondet stack, abort the program,
** with the abort message including the message in `error', and (if not NULL)
** the location in `where'.
**
** If maxfr *is* in one of the zones of the nondet stack, then update
** its MR_zone_max field if maxfr exceeds it, since the MR_zone_max field
** should always hold the highest address used in the zone so far.
*/
#if !defined(MR_HIGHLEVEL_CODE)
extern void MR_nondetstack_inclusion_check(MR_Word *maxfr,
const char *error, const char *where);
#endif
typedef enum {
MR_OVERFLOW_ZONE_DETSTACK,
MR_OVERFLOW_ZONE_NONDETSTACK,
MR_OVERFLOW_ZONE_HEAP,
MR_OVERFLOW_ZONE_OTHER
} MR_OverflowZone;
/*
** Output a message about a zone error to standard error and abort.
** This function is for fatal zone underflow and overflow errors
** in the Mercury runtime.
*/
MR_NO_RETURN(extern void \
MR_fatal_zone_error(MR_OverflowZone ptr_kind,
const char *ptr_name, const void *ptr,
const char *zone_name,
const MR_MemoryZone *zone, const MR_MemoryZones *zones,
const char *error, const char *where));
#ifndef MR_CHECK_FOR_OVERFLOW
#define MR_heap_overflow_check() ((void) 0)
#define MR_detstack_overflow_check() ((void) 0)
#define MR_detstack_overflow_check_msg(x) ((void) 0)
#define MR_detstack_underflow_check() ((void) 0)
#define MR_detstack_underflow_check_msg(x) ((void) 0)
#define MR_nondetstack_overflow_check() ((void) 0)
#define MR_nondetstack_overflow_check_msg(x) ((void) 0)
#define MR_nondetstack_underflow_check() ((void) 0)
#define MR_nondetstack_underflow_check_msg(x) ((void) 0)
#else /* MR_CHECK_FOR_OVERFLOW */
#include "mercury_regs.h"
#include "mercury_misc.h" /* for MR_fatal_error() */
#define MR_heap_overflow_check() \
( \
MR_IF (MR_hp >= MR_ENGINE(MR_eng_heap_zone)->MR_zone_top,( \
MR_fatal_error("heap overflow") \
)), \
MR_IF (MR_hp > MR_ENGINE(MR_eng_heap_zone)->MR_zone_max,( \
MR_ENGINE(MR_eng_heap_zone)->MR_zone_max = MR_hp \
)), \
(void)0 \
)
#define MR_detstack_overflow_check() \
( \
MR_IF (MR_sp >= MR_CONTEXT(MR_ctxt_detstack_zone)->MR_zone_top,( \
MR_fatal_error("stack overflow") \
)), \
MR_IF (MR_sp > MR_CONTEXT(MR_ctxt_detstack_zone)->MR_zone_max,( \
MR_CONTEXT(MR_ctxt_detstack_zone)->MR_zone_max = MR_sp \
)), \
(void)0 \
)
#define MR_detstack_overflow_check_msg(where) \
( \
MR_IF (MR_sp >= MR_CONTEXT(MR_ctxt_detstack_zone)->MR_zone_top,( \
MR_fatal_error("stack overflow: " where) \
)), \
MR_IF (MR_sp > MR_CONTEXT(MR_ctxt_detstack_zone)->MR_zone_max,( \
MR_CONTEXT(MR_ctxt_detstack_zone)->MR_zone_max = MR_sp \
)), \
(void)0 \
)
#define MR_detstack_underflow_check() \
( \
MR_IF (MR_sp < MR_CONTEXT(MR_ctxt_detstack_zone)->MR_zone_min,( \
MR_fatal_error("stack underflow") \
)), \
(void)0 \
)
#define MR_detstack_underflow_check_msg(where) \
( \
MR_IF (MR_sp < MR_CONTEXT(MR_ctxt_detstack_zone)->MR_zone_min,( \
MR_fatal_error("stack underflow: " where) \
)), \
(void)0 \
)
/*
** Checking for overflow and underflow on the nondet stack is not as simple
** as on the det stack. Since it is OK for MR_maxfr to be in a segment that
** is NOT currently the top nondet stack segment (see the comment on
** MR_new_nondetstack_segment to see why), we have check whether MR_maxfr
** is in *any* of the segments that currently belong to the nondet stack.
**
** MR_nondetstack_inclusion_check will set the MR_zone_max field of a zone
** if MR_maxfr exceeds it. It will test for this even during underflow checks,
** since testing whether the current check is for underflow would probably
** take just as long.
*/
#define MR_nondetstack_overflow_check() \
MR_nondetstack_inclusion_check(MR_maxfr, "nondetstack overflow", NULL)
#define MR_nondetstack_overflow_check_msg(where) \
MR_nondetstack_inclusion_check(MR_maxfr, "nondetstack overflow", where)
#define MR_nondetstack_underflow_check() \
MR_nondetstack_inclusion_check(MR_maxfr, "nondetstack underflow", NULL)
#define MR_nondetstack_underflow_check_msg(where) \
MR_nondetstack_inclusion_check(MR_maxfr, "nondetstack underflow", where)
#endif /* MR_CHECK_FOR_OVERFLOW */
#endif /* not MERCURY_OVERFLOW_H */