## highcode-baseops.pkg
#
# See overview comments in:
#
#
src/lib/compiler/back/top/highcode/highcode-baseops.api# Compiled by:
#
src/lib/compiler/core.sublib### "The mathematics are distinguished
### by a particular privilege,
### that is, in the course of ages,
### they may always advance and
### can never recede."
###
### -- Edward Gibbon,
### Decline and Fall of the Roman Empire
stipulate
package cty = ctypes; # ctypes is from
src/lib/compiler/back/low/ccalls/ctypes.pkgherein
package highcode_baseops
: (weak) Highcode_Baseops # Highcode_Baseops is from
src/lib/compiler/back/top/highcode/highcode-baseops.api {
# Number_Kind_And_Size gives kind of number (int/unt/float)
# plus size-in-bits:
#
Number_Kind_And_Size
#
= INT Int # Fixed-length signed-integer type.
| UNT Int
# Fixed-length unsigned-integer type.
| FLOAT Int
# Fixed-length floating-point type.
;
Math_Op
#
= ADD
| SUBTRACT | MULTIPLY | DIVIDE | NEGATE
# Int or Float. For int, this does Round-to-zero division -- this is the native instruction on Intel32.
| ABS | FSQRT | FSIN | FCOS | FTAN
# Float only.
| LSHIFT | RSHIFT | RSHIFTL
# Int only.
| BITWISE_AND | BITWISE_OR | BITWISE_XOR | BITWISE_NOT
# Int only.
| REM
# Int only. This does round-to-zero remainder -- this is the native instruction on Intel32.
| DIV
# Int only. This does round-to-negative-infinity division -- this will be much slower on Intel32, has to be faked.
| MOD
# Int only. This does round-to-negative-infinity remainder -- this will be much slower on Intel32, has to be faked.
;
Comparison_Op = GT
| GE | LT | LE | LEU | LTU | GEU | GTU | EQL | NEQ;
# Various base operations. Those that are designated "inline" by a
# _MACRO suffic on their name are expanded into lambda code in terms of other operators
# in
src/lib/compiler/back/top/translate/translate-deep-syntax-to-lambdacode.pkg # as is the "checkbounds=>TRUE" version of GET_VECSLOT_NUMERIC_CONTENTS or SET_VECSLOT_TO_NUMERIC_VALUE.
#
Baseop
#
= ARITH { op: Math_Op, overflow: Bool, kind_and_size: Number_Kind_And_Size }
| LSHIFT_MACRO Number_Kind_And_Size
| RSHIFT_MACRO Number_Kind_And_Size
| RSHIFTL_MACRO Number_Kind_And_Size
# "RSHIFTL" may be "right-shift logical", where "logical" means "without extending sign".
| COMPARE { op: Comparison_Op, kind_and_size: Number_Kind_And_Size }
#
| SHRINK_UNT (Int, Int)
| SHRINK_INT (Int, Int)
| CHOP (Int, Int)
| STRETCH (Int, Int)
| COPY (Int, Int)
#
| SHRINK_INTEGER Int
| CHOP_INTEGER Int
| STRETCH_TO_INTEGER Int
| COPY_TO_INTEGER Int
#
| ROUND { floor: Bool, from: Number_Kind_And_Size, to: Number_Kind_And_Size }
| CONVERT_FLOAT { from: Number_Kind_And_Size, to: Number_Kind_And_Size }
#
| GET_VECSLOT_NUMERIC_CONTENTS { kind_and_size: Number_Kind_And_Size, checkbounds: Bool, immutable: Bool }
# Stays same after the bounds-check gets expanded out in
src/lib/compiler/back/top/translate/translate-deep-syntax-to-lambdacode.pkg
| SET_VECSLOT_TO_NUMERIC_VALUE { kind_and_size: Number_Kind_And_Size, checkbounds: Bool }
# Stays same after the bounds-check gets expanded out in
src/lib/compiler/back/top/translate/translate-deep-syntax-to-lambdacode.pkg #
| MAKE_NONEMPTY_RW_VECTOR_MACRO
# Inline typeagnostic rw_vector creation.
#
| RW_VECTOR_GET
# Typeagnostic rw_vector fetch.
| RO_VECTOR_GET
# Typeagnostic vector fetch.
| RW_VECTOR_SET
# Store to vector. Winds up as unsafe::rw_vector::set. Updates the heap changelog.
#
| RW_VECTOR_GET_WITH_BOUNDSCHECK
# Typeagnostic rw_vector fetch. # Gets replaced by RW_VECTOR_GET after the bounds-check gets expanded in
src/lib/compiler/back/top/translate/translate-deep-syntax-to-lambdacode.pkg
| RO_VECTOR_GET_WITH_BOUNDSCHECK
# Typeagnostic vector fetch. # Gets replaced by RW_VECTOR_GET after the bounds-check gets expanded in
src/lib/compiler/back/top/translate/translate-deep-syntax-to-lambdacode.pkg
| RW_VECTOR_SET_WITH_BOUNDSCHECK
# Store to vector, inlined. Gets replaced by RW_VECTOR_SET after bounds-check is expanded out in
src/lib/compiler/back/top/translate/translate-deep-syntax-to-lambdacode.pkg #
| RW_MATRIX_GET_MACRO
# Fetch from typeagnostic rw_matrix.
| RO_MATRIX_GET_MACRO
# Fetch from typeagnostic matrix.
| RW_MATRIX_SET_MACRO
# rw_matrix update (maybe boxed).
#
| RW_MATRIX_GET_WITH_BOUNDSCHECK_MACRO
# Fetch from typeagnostic rw_matrix.
| RO_MATRIX_GET_WITH_BOUNDSCHECK_MACRO
# Fetch from typeagnostic matrix.
| RW_MATRIX_SET_WITH_BOUNDSCHECK_MACRO
# rw_matrix update (maybe boxed)
#
| POINTER_EQL
| POINTER_NEQ
# Pointer equality.
#
| POLY_EQL
| POLY_NEQ
# Typeagnostic equality.
#
| IS_BOXED
# ((i & 1) == 0) TRUE for pointers, FALSE for tagged ints -- see fun 'boxed' in
src/lib/compiler/back/low/main/main/translate-nextcode-to-treecode-g.pkg
| IS_UNBOXED
# ((i & 1) != 1) FALSE for pointers, TRUE for tagged ints -- see fun 'unboxed' in
src/lib/compiler/back/low/main/main/translate-nextcode-to-treecode-g.pkg #
| VECTOR_LENGTH_IN_SLOTS
# Vector, string, rw_vector, ... length
| HEAPCHUNK_LENGTH_IN_WORDS
# Length of arbitrary heap chunk, excluding tagword itself.
#
| CAST
# If this is introduced at all, it must(?) be in
src/lib/compiler/back/top/forms/drop-types-from-anormcode-junk.pkg
| WCAST
# This might have been weak sealing of packages at one point; I can find no evidence that it ever gets introduced by the current compiler.
#
| MARK_EXCEPTION_WITH_STRING
# Mark an exception value with a string.
#
| GET_RUNTIME_ASM_PACKAGE_RECORD
# Get the pointer to the run-vector. (This may be dead code -- I can't find where it gets implemented. -- 2011-08-24 CrT)
#
| GET_EXCEPTION_HANDLER_REGISTER
# Get exception-handler from dedicated register.
| SET_EXCEPTION_HANDLER_REGISTER
# Set exception-handler dedicated register. (On x86 this "register" is a ram location.)
#
| GET_CURRENT_MICROTHREAD_REGISTER
# Get dedicated 'current thread' register -- see current_thread_ptr in
src/lib/compiler/back/top/highcode/highcode-baseops.pkg
| SET_CURRENT_MICROTHREAD_REGISTER
# Set dedicated 'current thread' register. (On x86 this "register" is a ram location.)
#
| PSEUDOREG_GET | PSEUDOREG_SET
# Get/set pseudo registers.
| SETMARK | DISPOSE
# Capture/dispose frames.
#
| CALLCC
# Fate ("continuaton") operations.
| CALL_WITH_CURRENT_CONTROL_FATE
| THROW
| MAKE_ISOLATED_FATE
# "Isolating a function." Something involving setting the exception handler -- see
src/lib/compiler/back/top/nextcode/translate-anormcode-to-nextcode-g.pkg #
| MAKE_REFCELL
# Allocate a REF cell.
| GET_REFCELL_CONTENTS
# Implements the *ref op.
| SET_REFCELL
# Implements the ':=' op. Updates the heap changelog.
| SET_REFCELL_TO_TAGGED_INT_VALUE
# Implements the ':=' op for Ref(Tagged_Int) refcells. Does NOT update the heap changelog.
#
| SET_VECSLOT_TO_BOXED_VALUE
# Store in vector a String or Float64 value. Updates the heap changelog.
| SET_VECSLOT_TO_TAGGED_INT_VALUE
# Store in vector an Tagged_Int value. Does NOT update the heap changelog.
#
| GET_BATAG_FROM_TAGWORD
# Extract (b-tag << 2
| a-tag) from given tagword.
# Used in rep() in
src/lib/std/src/unsafe/unsafe-chunk.pkg # Used in poly_equal() in
src/lib/core/init/core.pkg #
| MAKE_WEAK_POINTER_OR_SUSPENSION
# Make a weak pointer or suspension.
| SET_STATE_OF_WEAK_POINTER_OR_SUSPENSION
# Set the state of a special chunk.
| GET_STATE_OF_WEAK_POINTER_OR_SUSPENSION
# Get the state of a special chunk.
| USELVAR | DEFLVAR
| MIN_MACRO Number_Kind_And_Size
# Inline min.
| MAX_MACRO Number_Kind_And_Size
# Inline max.
| ABS_MACRO Number_Kind_And_Size
# Inline abs.
| NOT_MACRO
# Inline bool not operator.
| COMPOSE_MACRO
# Inline compose ('o') operator.
| THEN_MACRO
# Inline "then" operator.
| IGNORE_MACRO
# Inline "ignore" function.
| ALLOCATE_RW_VECTOR_MACRO
# Inline typeagnostic rw_vector allocation.
| ALLOCATE_RO_VECTOR_MACRO
# Inline typeagnostic vector allocation.
| ALLOCATE_NUMERIC_RW_VECTOR_MACRO Number_Kind_And_Size
# Inline typelocked rw_vector allocation.
| ALLOCATE_NUMERIC_RO_VECTOR_MACRO Number_Kind_And_Size
# Inline typelocked vector allocation.
| MAKE_EXCEPTION_TAG
# Make a new exception tag.
| WRAP
# Box a value by wrapping it.
| UNWRAP
# Unbox a value by unwrapping it.
# Primops to support new
# rw_vector representations:
#
| MAKE_ZERO_LENGTH_VECTOR
# Allocate zero-length rw_vector header.
| GET_VECTOR_DATACHUNK
# Get data pointer from arr/vec header.
| RECORD_GET
# Fetch-from-record operation.
| RAW64_GET
# Fetch-from-raw64 operation.
# Primops to support new experimental
# C "foreign-function interface" (FFI).
#
| GET_FROM_NONHEAP_RAM Number_Kind_And_Size
# Load from arbitrary memory location.
| SET_NONHEAP_RAM Number_Kind_And_Size
# Store to arbitrary memory location.
| RAW_CCALL Null_Or { c_prototype: cty::Cfun_Type,
ml_argument_representations: List( Ccall_Type ),
ml_result_representation: Null_Or( Ccall_Type ),
is_reentrant: Bool
}
#
# RAW_CCALL makes a call to a C-function.
# The baseop carries C function prototype information and specifies
# which of its (ML-) arguments are floating point. C prototype
# information is for use by the backend, ML information is for
# use by the nextcode converter.
| RAW_ALLOCATE_C_RECORD { fblock: Bool }
#
# This allocates uninitialized storage on the heap.
# The record is meant to hold short-lived C chunks, i.e., they
# are not ML pointers. The representation is
# the same as RECORD with tag four_byte_aligned_nonpointer_data_btag or tag_fblock.
| IDENTITY_MACRO
# typeagnostic identity
| CVT64
# convert between external and
# internal representation of
# simulated 64-bit scalars
also
Ccall_Type = CCI32
| CCI64 | CCR64 | CCML;
# Default integer arithmetic and comparison operators:
#
iadd = ARITH { op=> ADD, overflow=>TRUE, kind_and_size=>INT 31 };
isub = ARITH { op=> SUBTRACT, overflow=>TRUE, kind_and_size=>INT 31 };
imul = ARITH { op=> MULTIPLY, overflow=>TRUE, kind_and_size=>INT 31 };
idiv = ARITH { op=> DIVIDE, overflow=>TRUE, kind_and_size=>INT 31 };
ineg = ARITH { op=> NEGATE, overflow=>TRUE, kind_and_size=>INT 31 };
ieql = COMPARE { op=>EQL, kind_and_size=>INT 31 };
ineq = COMPARE { op=>NEQ, kind_and_size=>INT 31 };
igt = COMPARE { op=> GT, kind_and_size=>INT 31 };
ilt = COMPARE { op=> LT, kind_and_size=>INT 31 };
ige = COMPARE { op=> GE, kind_and_size=>INT 31 };
ile = COMPARE { op=> LE, kind_and_size=>INT 31 };
# * default floating-point equality operator
feqld = COMPARE { op=>EQL, kind_and_size=>FLOAT 64 };
##########################################################################
# OTHER PRIMOP-RELATED UTILITY FUNCTIONS
##########################################################################
fun kind_and_size_to_string (INT 31) => ""; # Possible 64-BIT_ISSUE
kind_and_size_to_string (INT bits) => int::to_string bits;
kind_and_size_to_string (UNT 32) => "u"; # Possible 64-BIT_ISSUE
kind_and_size_to_string (UNT bits) => "u" + int::to_string bits;
kind_and_size_to_string (FLOAT 64) => "f";
kind_and_size_to_string (FLOAT bits) => "f" + int::to_string bits;
end;
cvt_param = int::to_string;
fun cvt_params (from, to)
=
cat [cvt_param from, "_", cvt_param to];
fun baseop_to_string (ARITH { op, overflow, kind_and_size } )
=>
cat [ case op
ADD => "+";
SUBTRACT => "-";
MULTIPLY => "*";
DIVIDE => "/";
NEGATE => "-_";
FSQRT => "fsqrt";
FSIN => "fsin";
FCOS => "fcos";
FTAN => "ftan";
LSHIFT => "lshift";
RSHIFT => "rshift";
RSHIFTL => "rshift_l";
BITWISE_AND => "bitwise_and";
BITWISE_OR => "bitwise_or";
BITWISE_XOR => "bitwise_xor";
BITWISE_NOT => "bitwise_not";
ABS => "abs";
REM => "rem";
DIV => "div";
MOD => "mod";
esac,
(overflow ?? "" :: "n"),
kind_and_size_to_string kind_and_size
];
baseop_to_string (LSHIFT_MACRO kind_and_size ) => "inllshift" + kind_and_size_to_string kind_and_size;
baseop_to_string (RSHIFT_MACRO kind_and_size ) => "inlrshift" + kind_and_size_to_string kind_and_size;
baseop_to_string (RSHIFTL_MACRO kind_and_size) => "inlrshiftl" + kind_and_size_to_string kind_and_size;
baseop_to_string (COMPARE { op, kind_and_size } )
=>
( case op
GT => ">";
LT => "<";
GE => ">=";
LE => "<=";
GEU => ">=U";
GTU => ">U";
LEU => "<=U";
LTU => "<U";
EQL => "=";
NEQ => "!=";
esac
+
kind_and_size_to_string kind_and_size
);
baseop_to_string (SHRINK_INT arg ) => "test_" + cvt_params arg;
baseop_to_string (SHRINK_UNT arg ) => "test_" + cvt_params arg;
baseop_to_string (STRETCH arg) => "extend" + cvt_params arg;
baseop_to_string (CHOP arg ) => "trunc" + cvt_params arg;
baseop_to_string (COPY arg ) => "copy" + cvt_params arg;
baseop_to_string (SHRINK_INTEGER i) => "test_inf_" + cvt_param i;
baseop_to_string (CHOP_INTEGER i) => "trunc_inf_" + cvt_param i;
baseop_to_string (STRETCH_TO_INTEGER i) => cat ["extend_", cvt_param i, "_inf"];
baseop_to_string (COPY_TO_INTEGER i) => cat ["copy_", cvt_param i, "_inf"];
baseop_to_string (ROUND { floor=>TRUE, from=>FLOAT 64, to=>INT 31 } ) => "floor";
baseop_to_string (ROUND { floor=>FALSE, from=>FLOAT 64, to=>INT 31 } ) => "round";
baseop_to_string (ROUND { floor, from, to } )
=>
( (floor ?? "floor" :: "round")
+
kind_and_size_to_string from
+
"_"
+
kind_and_size_to_string to
);
baseop_to_string (CONVERT_FLOAT { from=>INT 31, to=>FLOAT 64 } ) => "convert_float";
baseop_to_string (CONVERT_FLOAT { from, to } ) => ("convert_float" + kind_and_size_to_string from + "_" + kind_and_size_to_string to);
baseop_to_string (GET_VECSLOT_NUMERIC_CONTENTS { kind_and_size, checkbounds, immutable } )
=>
("get_vecslot_numeric_contents" + kind_and_size_to_string kind_and_size
+ (checkbounds ?? "<with-boundscheck>" :: "")
+ (immutable ?? "<immutable>" :: "")
);
baseop_to_string (SET_VECSLOT_TO_NUMERIC_VALUE { kind_and_size, checkbounds } ) => ("numupdate" + kind_and_size_to_string kind_and_size + (if checkbounds "<checkbounds>"; else "";fi));
baseop_to_string GET_REFCELL_CONTENTS => "*_";
baseop_to_string SET_REFCELL => ":=";
baseop_to_string SET_REFCELL_TO_TAGGED_INT_VALUE => "(to Ref(Tagged_Int)):=";
baseop_to_string IS_BOXED => "is_boxed";
baseop_to_string IS_UNBOXED => "is_unboxed";
baseop_to_string CAST => "cast";
baseop_to_string WCAST => "wcast";
baseop_to_string POINTER_EQL => "pointer_eql";
baseop_to_string POINTER_NEQ => "pointer_neq";
baseop_to_string POLY_EQL => "polyeql";
baseop_to_string POLY_NEQ => "polyneq";
baseop_to_string GET_EXCEPTION_HANDLER_REGISTER => "get_exception_handler_register";
baseop_to_string MAKE_REFCELL => "makeref";
baseop_to_string SET_EXCEPTION_HANDLER_REGISTER => "set_exception_handler_register";
baseop_to_string VECTOR_LENGTH_IN_SLOTS => "vector_length_in_slots";
baseop_to_string HEAPCHUNK_LENGTH_IN_WORDS => "heapchunk_length_in_words";
baseop_to_string CALLCC => "callcc";
baseop_to_string CALL_WITH_CURRENT_CONTROL_FATE => "call_with_current_control_fate";
baseop_to_string MAKE_ISOLATED_FATE => "make_isolated_fate";
baseop_to_string THROW => "throw";
baseop_to_string RW_VECTOR_GET => "get_rw_vecslot_contents";
baseop_to_string SET_VECSLOT_TO_TAGGED_INT_VALUE => "set_vecslot_to_tagged_int";
baseop_to_string SET_VECSLOT_TO_BOXED_VALUE => "set_vecslot_to_boxedvalue";
baseop_to_string RW_VECTOR_SET => "set_vecslot";
baseop_to_string RW_VECTOR_GET_WITH_BOUNDSCHECK => "get_rw_vecslot_contents_after_bounds_check";
baseop_to_string RO_VECTOR_GET_WITH_BOUNDSCHECK => "get_ro_vecslot_contents_after_bounds_check";
baseop_to_string RW_VECTOR_SET_WITH_BOUNDSCHECK => "set_vecslot_after_bounds_check";
baseop_to_string MAKE_NONEMPTY_RW_VECTOR_MACRO => "inlmkarray";
baseop_to_string RO_VECTOR_GET => "get_ro_vecslot_contents";
baseop_to_string GET_RUNTIME_ASM_PACKAGE_RECORD => "getrunvec";
baseop_to_string GET_CURRENT_MICROTHREAD_REGISTER => "get_current_microthread_register";
baseop_to_string SET_CURRENT_MICROTHREAD_REGISTER => "set_current_microthread_register";
baseop_to_string PSEUDOREG_GET => "getpseudo";
baseop_to_string PSEUDOREG_SET => "setpseudo";
baseop_to_string SETMARK => "setmark";
baseop_to_string DISPOSE => "dispose";
baseop_to_string GET_BATAG_FROM_TAGWORD => "get_batag_from_tagword";
baseop_to_string MAKE_WEAK_POINTER_OR_SUSPENSION => "make_weak_pointer_or_suspension";
baseop_to_string SET_STATE_OF_WEAK_POINTER_OR_SUSPENSION => "set_state_of_weak_pointer_or_suspension";
baseop_to_string GET_STATE_OF_WEAK_POINTER_OR_SUSPENSION => "get_state_of_weak_pointer_or_suspension";
baseop_to_string USELVAR => "uselvar";
baseop_to_string DEFLVAR => "deflvar";
baseop_to_string (MIN_MACRO nk) => cat ["inlmin(", kind_and_size_to_string nk, ")"];
baseop_to_string (MAX_MACRO nk) => cat ["inlmax(", kind_and_size_to_string nk, ")"];
baseop_to_string (ABS_MACRO nk) => cat ["inlabs(", kind_and_size_to_string nk, ")"];
baseop_to_string NOT_MACRO => "inlnot";
baseop_to_string COMPOSE_MACRO => "inlcompose";
baseop_to_string THEN_MACRO => "inlthen";
baseop_to_string IGNORE_MACRO => "inlignore";
baseop_to_string (ALLOCATE_RW_VECTOR_MACRO) => "inl_array";
baseop_to_string (ALLOCATE_RO_VECTOR_MACRO) => "inl_vector";
baseop_to_string (ALLOCATE_NUMERIC_RW_VECTOR_MACRO kind_and_size) => cat ["inl_monoarray(", kind_and_size_to_string kind_and_size, ")"];
baseop_to_string (ALLOCATE_NUMERIC_RO_VECTOR_MACRO kind_and_size) => cat ["inl_monovector(", kind_and_size_to_string kind_and_size, ")"];
baseop_to_string (MARK_EXCEPTION_WITH_STRING) => "markexn";
baseop_to_string RO_MATRIX_GET_MACRO => "ro_matrix_get";
baseop_to_string RW_MATRIX_GET_MACRO => "rw_matrix_get";
baseop_to_string RW_MATRIX_SET_MACRO => "rw_matrix_set";
baseop_to_string RO_MATRIX_GET_WITH_BOUNDSCHECK_MACRO => "ro_matrix_get_with_boundscheck";
baseop_to_string RW_MATRIX_GET_WITH_BOUNDSCHECK_MACRO => "rw_matrix_get_with_boundscheck";
baseop_to_string RW_MATRIX_SET_WITH_BOUNDSCHECK_MACRO => "rw_matrix_set_with_boundscheck";
baseop_to_string MAKE_EXCEPTION_TAG => "mketag";
baseop_to_string WRAP => "wrap";
baseop_to_string UNWRAP => "unwrap";
# Primops to support new rw_vector representations:
#
baseop_to_string MAKE_ZERO_LENGTH_VECTOR => "make_zero_length_vector";
baseop_to_string GET_VECTOR_DATACHUNK => "getseqdata";
baseop_to_string RECORD_GET => "get_recslot_contents";
baseop_to_string RAW64_GET => "get_raw64slot_contents";
# Primops to support new experimental
# C "foreign-function interface" (FFI):
#
baseop_to_string (GET_FROM_NONHEAP_RAM nk) => cat ["raw_load(", kind_and_size_to_string nk, ")"];
baseop_to_string (SET_NONHEAP_RAM nk) => cat ["raw_store(", kind_and_size_to_string nk, ")"];
baseop_to_string (RAW_CCALL _) => "raw_ccall";
baseop_to_string (RAW_ALLOCATE_C_RECORD { fblock } ) => cat ["raw_", if fblock "fblock"; else "iblock";fi, "_record"];
baseop_to_string IDENTITY_MACRO => "inlidentity";
baseop_to_string CVT64 => "cvt64";
end;
# TRUE means "May not be dead-code eliminated":
#
fun might_have_side_effects (ARITH { overflow, ... }) => overflow;
#
might_have_side_effects (RSHIFT_MACRO _) => FALSE;
might_have_side_effects (RSHIFTL_MACRO _) => FALSE;
#
might_have_side_effects (COMPARE _) => FALSE;
#
might_have_side_effects (STRETCH _) => FALSE;
might_have_side_effects (CHOP _) => FALSE;
might_have_side_effects (COPY _) => FALSE;
#
might_have_side_effects POINTER_EQL => FALSE;
might_have_side_effects POINTER_NEQ => FALSE;
#
might_have_side_effects POLY_EQL => FALSE;
might_have_side_effects POLY_NEQ => FALSE;
#
might_have_side_effects IS_BOXED => FALSE;
might_have_side_effects IS_UNBOXED => FALSE;
#
might_have_side_effects VECTOR_LENGTH_IN_SLOTS => FALSE;
might_have_side_effects HEAPCHUNK_LENGTH_IN_WORDS => FALSE;
#
might_have_side_effects CAST => FALSE;
might_have_side_effects WCAST => FALSE;
#
might_have_side_effects (MIN_MACRO _) => FALSE;
might_have_side_effects (MAX_MACRO _) => FALSE;
might_have_side_effects NOT_MACRO => FALSE;
might_have_side_effects COMPOSE_MACRO => FALSE;
might_have_side_effects IGNORE_MACRO => FALSE;
#
might_have_side_effects WRAP => FALSE;
might_have_side_effects UNWRAP => FALSE;
#
might_have_side_effects IDENTITY_MACRO => FALSE;
might_have_side_effects CVT64 => FALSE;
#
might_have_side_effects _ => TRUE;
end;
#
# should return more than just a boolean:
# { Store, Fate }-{ read, write } XXX BUGGO FIXME
fun might_raise_exception (ROUND _) => TRUE; # Currently nowhere used.
might_raise_exception MAKE_NONEMPTY_RW_VECTOR_MACRO => TRUE;
#
might_raise_exception RW_VECTOR_GET_WITH_BOUNDSCHECK => TRUE;
might_raise_exception RO_VECTOR_GET_WITH_BOUNDSCHECK => TRUE;
might_raise_exception RW_VECTOR_SET_WITH_BOUNDSCHECK => TRUE;
#
might_raise_exception RW_MATRIX_GET_WITH_BOUNDSCHECK_MACRO => TRUE;
might_raise_exception RO_MATRIX_GET_WITH_BOUNDSCHECK_MACRO => TRUE;
might_raise_exception RW_MATRIX_SET_WITH_BOUNDSCHECK_MACRO => TRUE;
#
might_raise_exception (ARITH { overflow, ... }) => overflow;
#
might_raise_exception (GET_VECSLOT_NUMERIC_CONTENTS { checkbounds, ... }) => checkbounds;
might_raise_exception (SET_VECSLOT_TO_NUMERIC_VALUE { checkbounds, ... }) => checkbounds;
#
might_raise_exception _ => FALSE;
end;
}; # package highcode_baseops
end;