## highcode-baseops.api
#
# The base-functions vocabulary used in lambdacode and anormcode.
#
# For general background see:
#
# src/A.COMPILER-PASSES.OVERVIEW
# Compiled by:
#
src/lib/compiler/core.sublib############################################################################
#
# Int/Unt Conversions Explained
#
# All Un/signed integer conversion operations are expressed using five
# base conversion operators. Algebraic equations over these
# operators are easy to define and can be used to simplify composition
# of conversion operations.
#
# There are five basic conversion operators.
#
# SHRINK_INT, SHRINK_UNT, and CHOP are used to go from large values to small ones;
# STRETCH and COPY are used to go from small values to large.
#
# The operators STRETCH, CHOP, and COPY are "pure, " while SHRINK_INT
# and SHRINK_UNT may raise OVERFLOW.
# In all cases, we assume that (n >= m):
#
# SHRINK_INT (n, m) -- map a signed n-bit value to an m-bit 2's
# complement value; raise OVERFLOW if the value
# is too large.
#
# SHRINK_UNT (n, m) map an unsigned n-bit value to an m-bit 2's
# complement value; raise OVERFLOW if the value
# is too large.
#
# STRETCH (m, n) -- sign extend an m-bit value to a n-bit value
#
# CHOP (n, m) -- truncate an n-bit value to an m-bit value.
#
# COPY (m, n) -- copy an m-bit value to an n-bit value.
#
#
# Conversions where the sizes are the same can be simplified to copies:
#
# SHRINK_INT (n, n) == COPY (n, n)
# STRETCH (n, n) == COPY (n, n) Note: this does not apply to SHRINK_UNT
# CHOP (n, n) == COPY (n, n)
#
# The translation of conversion operations in the one_word_unt and one_byte_unt
# packages (for example) is given by:
#
# Package function => Implemented by
# ---------- -------------- ---------------------
# one_word_unt toLargeInt => SHRINK_UNT (32, 32)
# toLargeIntX => STRETCH (32, 32) = COPY (32, 32)
# from_large_int => COPY (32, 32)
# toInt => SHRINK_UNT (32, 31)
# toIntX => SHRINK_INT (32, 31)
# from_int => STRETCH (31, 32)
# toLargeUnt => COPY (32, 32)
# toLargeUntX => STRETCH (32, 32) = COPY (32, 32)
# fromLargeUnt => CHOP (32, 32) = COPY (32, 32)
#
# one_byte_unt toLargeInt => COPY ( 8, 32)
# toLargeIntX => STRETCH ( 8, 32)
# from_large_int => CHOP (32, 8)
# toInt => COPY ( 8, 31)
# toIntX => STRETCH ( 8, 31)
# from_int => CHOP (31, 8)
# toLargeUnt => COPY ( 8, 32)
# toLargeUntX => STRETCH ( 8, 32)
# fromLargeUnt => CHOP (32, 8)
#
#
# Each operator composed with itself is itself, but with different parameters:
#
# SHRINK_INT (n,m) o SHRINK_INT (p,n) == SHRINK_INT (p,m)
# SHRINK_UNT (n,m) o SHRINK_UNT (p,n) == SHRINK_UNT (p,m)
# STRETCH (n,m) o STRETCH (p,n) == STRETCH (p,m)
# CHOP (n,m) o CHOP (p,n) == CHOP (p,m)
# COPY (n,m) o COPY (p,n) == COPY (p,m)
#
# The composition of these operators can be described by a simple algebra:
#
# STRETCH (n,m) o COPY (p,n) == COPY (p,m) if (n > p), STRETCH (p,m) if (n == p)
# COPY (n,m) o STRETCH (p,n) == STRETCH (p,m) if (n == m)
# CHOP (n,m) o COPY (p,n) == COPY (p,m) if (m >= p) CHOP (p,m) if (m < p)
# COPY (n,m) o CHOP (p,n) == CHOP (p,m) if (n == m)
# SHRINK_INT (n,m) o COPY (p,n) == COPY (p,m) if (m >= p) SHRINK_INT (p,m) if (m < p)
# SHRINK_UNT (n,m) o COPY (p,n) == COPY (p,m) if (m >= p) SHRINK_UNT (p,m) if (m < p)
# COPY (n,m) o SHRINK_INT (p,n) == SHRINK_INT (p,m) if (n == m)
# COPY (n,m) o SHRINK_UNT (p,n) == SHRINK_UNT (p,m) if (n == m)
# CHOP (n,m) o STRETCH (p,n) == STRETCH (p,m) if (m >= p) CHOP (p,m) if (m < p)
# SHRINK_INT (n,m) o STRETCH (p,n) == STRETCH (p,m) if (m >= p) SHRINK_INT (p,m) if (m < p)
# SHRINK_UNT (n,m) o STRETCH (p,n) == STRETCH (p,m) if (m >= p) SHRINK_UNT (p,m) if (m < p)
#
# For example, consider:
# unt::toInt o unt::fromLargeUnt o one_byte_unt::toLargeUnt
#
# This translates to:
#
# SHRINK_UNT(31,31) o CHOP(32,31) o COPY(8,32)
#
# and simplifies to:
#
# SHRINK_UNT(31,31) o COPY(8,31)
#
# This further simplifies to:
#
# COPY(8,31)
#
# Since both 8-bit and 31-bit quantities are tagged the same way, this
# gets translated to a MOVE. With a smart register allocator that MOVE
# can be eliminated.
#
############################################################################
### "Every minute dies a man, Every minute one is born;"
###
### I need hardly point out to you that this calculation
### would tend to keep the sum total of the world's population
### in a state of perpetual equipoise, whereas it is a
### well-known fact that the said sum total is constantly
### on the increase.
###
### I would therefore take the liberty of suggesting that
### in the next edition of your excellent poem the erroneous
### calculation to which I refer should be corrected as follows:
###
### "Every moment dies a man, And one and a sixteenth is born."
###
### I may add that the exact figures are 1.067, but something must,
### of course, be conceded to the laws of metre.
###
### ~Charles Babbage,
### letter to Alfred, Lord Tennyson,
### about a couplet in his "The Vision of Sin"
stipulate
package cty = ctypes; # ctypes is from
src/lib/compiler/back/low/ccalls/ctypes.pkgherein
# This api is implemented in:
#
#
src/lib/compiler/back/top/highcode/highcode-baseops.pkg #
api Highcode_Baseops {
#
# 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 ops. Those that are designated _MACRO ("inline") 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.
# GET_VECSLOT_NUMERIC_CONTENTS and SET_VECSLOT_TO_NUMERIC_VALUE are for vectors of floats or ints
# stored WITHOUT boxing or tags.
#
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" is probably "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
# Integer -> Int
| CHOP_INTEGER Int
# Integer -> Int
| STRETCH_TO_INTEGER Int
# Int -> Integer
| COPY_TO_INTEGER Int
# Int -> Integer
| 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 }
| SET_VECSLOT_TO_NUMERIC_VALUE { kind_and_size: Number_Kind_And_Size, checkbounds: Bool }
| MAKE_NONEMPTY_RW_VECTOR_MACRO
# Make typeagnostic rw_vector.
#
| RW_VECTOR_GET
# Fetch from typeagnostic rw_vector.
| RO_VECTOR_GET
# Fetch from typeagnostic vector.
| RW_VECTOR_SET
# rw_vector update (maybe boxed). Updates the heap changelog.
#
| RW_VECTOR_GET_WITH_BOUNDSCHECK
# Fetch from typeagnostic rw_vector. # 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
# Fetch from typeagnostic vector. # 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
# rw_vector update (maybe boxed) Becomes 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
# This is just (x&1)==0 -- checks that we don't have a Tagged_Int value.
| IS_UNBOXED
# This is just (x&1)!=0 -- checks that we DO have a Tagged_Int value.
#
| VECTOR_LENGTH_IN_SLOTS
# Length of vector, string, rw_vector, ...
| HEAPCHUNK_LENGTH_IN_WORDS
# Length of arbitrary heapchunk, 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.
#
| GET_RUNTIME_ASM_PACKAGE_RECORD
# (This may be dead code; I can't find any implementation. --2011-08-24 CrT) Get runtime::asm vector -- see src/c/main/construct-runtime-package.c,
src/lib/core/init/runtime.pkg #
| MARK_EXCEPTION_WITH_STRING
# Mark an exception value with a string
#
| GET_EXCEPTION_HANDLER_REGISTER
# Get exception handler pointer.
| SET_EXCEPTION_HANDLER_REGISTER
# Set exception handler pointer.
#
| GET_CURRENT_MICROTHREAD_REGISTER
# Get "current thread" register contents.
| SET_CURRENT_MICROTHREAD_REGISTER
# Set "current thread" register contents.
#
| PSEUDOREG_GET
| PSEUDOREG_SET
# Get/set pseudo registers. This appears to be code that died a-borning.
#
| SETMARK | DISPOSE
# Capture/dispose frames.
#
| CALLCC
# Fate ("continuation") 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_TO_TAGGED_INT_VALUE
# Implements the ':=' op on Ref(Tagged_Int) refcells. Does NOT update the heap changelog.
| SET_REFCELL
# Implements the ':=' op. Updates the heap changelog.
| SET_VECSLOT_TO_BOXED_VALUE
# Used to store String and Float64 into a vector. Updates the heap changelog.
| SET_VECSLOT_TO_TAGGED_INT_VALUE
# Update rw_vector of integers WITH tags 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
#
| SET_STATE_OF_WEAK_POINTER_OR_SUSPENSION
#
| GET_STATE_OF_WEAK_POINTER_OR_SUSPENSION
#
| 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.
| GET_VECTOR_DATACHUNK
# Get data pointer from vector/rw_vector header
| RECORD_GET
# Fetch-from-record operation.
| RAW64_GET
# Fetch-from-raw64 operation.
# Primops to support new experimental C 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
}
#
# Make 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 FPS converter.
| RAW_ALLOCATE_C_RECORD { fblock: Bool }
#
# Allocate uninitialized storage on the heap.
# The record is meant to hold short-lived C chunks, i.e.,
# they are not Mythryl pointers. The representation is
# the same as RECORD with tag
# four_byte_aligned_nonpointer_data_btag (fblock = FALSE), # 32-bit int data.
# or tag_fblock (fblock = TRUE). # 64-bit float data.
| IDENTITY_MACRO
# typeagnostic identity
| CVT64
# convert between external and
# internal representation of
# simulated 64-bit scalars
also
Ccall_Type
= CCI32 # Passed as Int1.
| CCI64
# Passed as Int2 -- currently unused.
| CCR64
# Passed as Float64.
| CCML
# Passed as unsafe::unsafe_chunk::chunk.
;
iadd: Baseop; # Default integer addition.
isub: Baseop; # Default integer subtraction.
imul: Baseop;
idiv: Baseop;
ineg: Baseop;
feqld: Baseop;
ieql: Baseop;
ineq: Baseop;
igt: Baseop;
ilt: Baseop;
ile: Baseop;
ige: Baseop;
kind_and_size_to_string: Number_Kind_And_Size -> String;
baseop_to_string: Baseop -> String;
might_raise_exception: Baseop -> Bool; # TRUE means "Might raise exception". # Currently nowhere used.
might_have_side_effects: Baseop -> Bool; # TRUE means "May not be dead-code eliminated".
}; # api Highcode_Baseops
end;
## Copyright 1996 by AT&T Bell Laboratories
## Subsequent changes by Jeff Prothero Copyright (c) 2010-2015,
## released per terms of SMLNJ-COPYRIGHT.