Module: internal Copyright: Original Code is Copyright (c) 1995-2004 Functional Objects, Inc. All rights reserved. License: Functional Objects Library Public License Version 1.0 Dual-license: GNU Lesser General Public License Warranty: Distributed WITHOUT WARRANTY OF ANY KIND ////////////////////////////////////////////////////////////////////////////// // Some useful type constants. // A raw machine word which is non-negative and less than the word size. // This range doesn't actually need to be checked; the caller is expected // to do the range checking. define inline constant = ; ////////////////////////////////////////////////////////////////////////////// // Conversions between integers and machine integers // // Most of the conversion definitions are located in files specific to to // particular integer representation scheme. Only the common definitions // are located here. define inline-only function coerce-abstract-integer-to-machine-word (x :: ) => (result :: ) primitive-wrap-machine-word(primitive-unwrap-abstract-integer(x)) end function coerce-abstract-integer-to-machine-word; define inline-only function coerce-machine-word-to-unsigned-abstract-integer (x :: ) => (result :: ) primitive-wrap-unsigned-abstract-integer(primitive-unwrap-machine-word(x)) end function coerce-machine-word-to-unsigned-abstract-integer; define inline function as-unsigned (t :: , m :: ) as(t, coerce-machine-word-to-unsigned-abstract-integer(m)) end function as-unsigned; /// These "convenience" functions are exported for external use. ///---*** Compiler "bug" causes bogus warnings/code if return type is declared! define inline-only function integer-as-raw (x :: ) /*=> (raw-x :: )*/ primitive-unwrap-machine-word(coerce-integer-to-machine-word(x)) end function integer-as-raw; ///---*** Compiler "bug" causes bogus warnings/code if return type is declared! define inline-only function interpret-integer-as-raw (x :: ) /*=> (raw-x :: )*/ primitive-unwrap-machine-word(interpret-integer-as-machine-word(x)) end function interpret-integer-as-raw; interpret-integer-as-raw; // USED IN COMPILER define inline-only function raw-as-integer (raw-x :: ) => (x :: ) coerce-machine-word-to-integer(primitive-wrap-machine-word(raw-x)) end function raw-as-integer; ///---*** Compiler "bug" causes bogus warnings/code if return type is declared! define inline-only function abstract-integer-as-raw (x :: ) /*=> (raw-x :: )*/ primitive-unwrap-machine-word(coerce-abstract-integer-to-machine-word(x)) end function abstract-integer-as-raw; define inline-only function raw-as-abstract-integer (raw-x :: ) => (x :: ) coerce-machine-word-to-abstract-integer(primitive-wrap-machine-word(raw-x)) end function raw-as-abstract-integer; /// A "" is always an so, if a is too large /// to be converted into an , we'll just take its most significant bits /// for use as the . define inline-only function machine-word-as-hash-index (x :: ) => (hi :: ) if (machine-word-is-integer?(x)) coerce-machine-word-to-integer(x) else interpret-machine-word-as-integer(force-integer-tag(x)) end end function machine-word-as-hash-index; /// TODO: SHOULD BE OPTIMIZER THAT MAKES THIS IRRELEVANT define sealed inline method as (class == , x :: ) => (res :: ) x end method; ////////////////////////////////////////////////////////////////////////////// // Machine word size define inline-only function word-size () => (result :: ) // !@#$ this may not ultimately be the correct primitive for this, // In kab's spec for machine words there never was a primitive for // turning a raw machine word directly into an integer. A primitive // is needed here to prevent infinite recursion, and this value is // guaranteed to be in the fixnum range. raw-as-integer (primitive-machine-word-multiply-low (integer-as-raw(8), primitive-word-size())) end function word-size; ////////////////////////////////////////////////////////////////////////////// // Comparison define macro comparison-definer { define comparison ?:name } => { define inline-only function ?name (x :: , y :: ) => (result :: ) let raw-x :: = primitive-unwrap-machine-word(x); let raw-y :: = primitive-unwrap-machine-word(y); "primitive-" ## ?name(raw-x, raw-y) end function ?name } end macro; define comparison machine-word-equal?; define comparison machine-word-less-than?; ////////////////////////////////////////////////////////////////////////////// // Comparison predicates ///---*** NOTE: As a temporary fix for bug 628, the comparison operators for ///---*** vs. will coerce the ///---*** into a which can potentially overflow. Once the necessary ///---*** changes are made to the FFI to allow primitive-wrap-abstract-integer ///---*** to actually return s instead of s, ///---*** restore the commented-out versions of these predicates! define macro comparison-predicate-definer { define comparison-predicate ?:name ?lowlevel:name } => { define sealed inline method ?name (x :: , y :: ) => (result :: ) ?lowlevel(x, y) end method ?name; define sealed inline method ?name (x :: , y :: ) => (result :: ) ?name(x, coerce-abstract-integer-to-machine-word(y)) //---*** ?name(coerce-machine-word-to-abstract-integer(x), y) end method ?name; define sealed inline method ?name (x :: , y :: ) => (result :: ) ?name(coerce-abstract-integer-to-machine-word(x), y) //---*** ?name(x, coerce-machine-word-to-abstract-integer(y)) end method ?name; } end macro; define comparison-predicate \= machine-word-equal?; define comparison-predicate \< machine-word-less-than?; ////////////////////////////////////////////////////////////////////////////// // Logical define macro logical-definer { define logical ?:name } => { define inline-only function ?name (x :: , y :: ) => (result :: ) let raw-x :: = primitive-unwrap-machine-word(x); let raw-y :: = primitive-unwrap-machine-word(y); primitive-wrap-machine-word("primitive-" ## ?name(raw-x, raw-y)) end function ?name } end macro; define logical machine-word-logior; define logical machine-word-logxor; define logical machine-word-logand; define inline-only function machine-word-lognot (x :: ) => (result :: ) primitive-wrap-machine-word (primitive-machine-word-lognot(primitive-unwrap-machine-word(x))) end function machine-word-lognot; define inline-only function machine-word-logbit? (index :: , x :: ) => (result :: ) let raw-index :: = integer-as-raw(index); let raw-x :: = primitive-unwrap-machine-word(x); primitive-machine-word-logbit?(raw-index, raw-x) end function machine-word-logbit?; define inline-only function machine-word-logbit-deposit (z :: , index :: , x :: ) => (result :: ) let raw-index :: = integer-as-raw(index); let raw-x :: = primitive-unwrap-machine-word(x); if (z) primitive-wrap-machine-word (primitive-machine-word-logbit-set(raw-index, raw-x)) else primitive-wrap-machine-word (primitive-machine-word-logbit-clear(raw-index, raw-x)) end if end function machine-word-logbit-deposit; define inline-only function machine-word-bit-field-extract (offset :: , size :: , x :: ) => (result :: ) let raw-offset :: = integer-as-raw(offset); let raw-size :: = integer-as-raw(size); let raw-x :: = primitive-unwrap-machine-word(x); primitive-wrap-machine-word (primitive-machine-word-bit-field-extract (raw-offset, raw-size, raw-x)) end function machine-word-bit-field-extract; define inline-only function machine-word-bit-field-deposit (field :: , offset :: , size :: , x :: ) => (result :: ) let raw-field :: = primitive-unwrap-machine-word(field); let raw-offset :: = integer-as-raw(offset); let raw-size :: = integer-as-raw(size); let raw-x :: = primitive-unwrap-machine-word(x); primitive-wrap-machine-word (primitive-machine-word-bit-field-deposit (raw-field, raw-offset, raw-size, raw-x)) end function machine-word-bit-field-deposit; define macro counter-definer { define counter ?:name } => { define inline-only function ?name (x :: ) => (result :: ) let raw-x :: = primitive-unwrap-machine-word(x); raw-as-integer("primitive-" ## ?name(raw-x)) end function ?name } end macro; define counter machine-word-count-low-zeros; define counter machine-word-count-high-zeros; ////////////////////////////////////////////////////////////////////////////// // Arithmetic define macro simple-arithmetic-definer { define simple-arithmetic ?:name } => { define inline-only function ?name (x :: , y :: ) => (result :: , overflow? :: ) let raw-x :: = primitive-unwrap-machine-word(x); let raw-y :: = primitive-unwrap-machine-word(y); let (result :: , overflow? :: ) = "primitive-" ## ?name(raw-x, raw-y); values(primitive-wrap-machine-word(result), overflow?) end function ?name } end macro; define simple-arithmetic machine-word-add-with-overflow; define simple-arithmetic machine-word-subtract-with-overflow; define inline-only function machine-word-multiply-with-overflow (x :: , y :: ) => (result-low :: , result-high :: , overflow? :: ) let raw-x :: = primitive-unwrap-machine-word(x); let raw-y :: = primitive-unwrap-machine-word(y); let (low :: , high :: , overflow? :: ) = primitive-machine-word-multiply-with-overflow(raw-x, raw-y); values(primitive-wrap-machine-word(low), primitive-wrap-machine-word(high), overflow?) end function machine-word-multiply-with-overflow; define macro sign-adjust-definer { define sign-adjust ?:name } => { define inline-only function ?name (x :: ) => (result :: , overflow? :: ) let raw-x :: = primitive-unwrap-machine-word(x); let (result :: , overflow? :: ) = "primitive-" ## ?name(raw-x); values(primitive-wrap-machine-word(result), overflow?) end function ?name } end macro; define sign-adjust machine-word-negative-with-overflow; define sign-adjust machine-word-abs-with-overflow; ////////////////////////////////////////////////////////////////////////////// // Division define macro signed-division-definer { define signed-division ?:name } => { define inline-only function ?name (dividend :: , divisor :: ) => (quotient :: , remainder :: ) let raw-dividend :: = primitive-unwrap-machine-word(dividend); let raw-divisor :: = primitive-unwrap-machine-word(divisor); let (quotient :: , remainder :: ) = "primitive-" ## ?name(raw-dividend, raw-divisor); values(primitive-wrap-machine-word(quotient), primitive-wrap-machine-word(remainder)) end function ?name } end macro; define signed-division machine-word-floor/; define signed-division machine-word-ceiling/; define signed-division machine-word-round/; define signed-division machine-word-truncate/; define signed-division machine-word-divide; ////////////////////////////////////////////////////////////////////////////// // Shift define inline-only function machine-word-shift-left-with-overflow (x :: , count :: ) => (low :: , high :: , overflow? :: ) let raw-x :: = primitive-unwrap-machine-word(x); let raw-count :: = integer-as-raw(count); let (low :: , high :: , overflow? :: ) = primitive-machine-word-shift-left-with-overflow(raw-x, raw-count); values(primitive-wrap-machine-word(low), primitive-wrap-machine-word(high), overflow?) end function machine-word-shift-left-with-overflow; define inline-only function machine-word-shift-right (x :: , count :: ) => (result :: ) let raw-x :: = primitive-unwrap-machine-word(x); // !@#$ this may not ultimately be the correct primitive for this, // In kab's spec for machine words there never was a primitive for // turning an integer directly into a raw machine word. A primitive // is needed here to prevent infinite recursion, and this value is // guaranteed to be in the fixnum range. let raw-count :: = integer-as-raw(count); primitive-wrap-machine-word (primitive-machine-word-shift-right(raw-x, raw-count)) end function machine-word-shift-right; ////////////////////////////////////////////////////////////////////////////// // Unsigned define macro unsigned-arithmetic-definer { define unsigned-arithmetic ?:name } => { define inline-only function ?name (x :: , y :: ) => (v1 :: , v2 :: ) let raw-x :: = primitive-unwrap-machine-word(x); let raw-y :: = primitive-unwrap-machine-word(y); let (v1 :: , v2 :: ) = "primitive-" ## ?name(raw-x, raw-y); values(primitive-wrap-machine-word(v1), primitive-wrap-machine-word(v2)) end function ?name } end macro; define unsigned-arithmetic machine-word-unsigned-add-with-carry; define unsigned-arithmetic machine-word-unsigned-subtract-with-borrow; define unsigned-arithmetic machine-word-unsigned-multiply; define unsigned-arithmetic machine-word-unsigned-divide; define macro unsigned-shift-definer { define unsigned-shift ?:name } => { define inline-only function ?name (x :: , count :: ) => (result :: ) let raw-x :: = primitive-unwrap-machine-word(x); let raw-count :: = integer-as-raw(count); primitive-wrap-machine-word ("primitive-" ## ?name(raw-x, raw-count)) end function ?name } end macro; define unsigned-shift machine-word-unsigned-rotate-left; define unsigned-shift machine-word-unsigned-rotate-right; define unsigned-shift machine-word-unsigned-shift-right; define inline-only function machine-word-unsigned-shift-left (x :: , count :: ) => (result :: ) let raw-x :: = primitive-unwrap-machine-word(x); let raw-count :: = integer-as-raw(count); primitive-wrap-machine-word (primitive-machine-word-unsigned-double-shift-left-high (integer-as-raw(0), raw-x, raw-count)) end function machine-word-unsigned-shift-left; define inline-only function machine-word-unsigned-less-than? (x :: , y :: ) => (result :: ) let raw-x :: = primitive-unwrap-machine-word(x); let raw-y :: = primitive-unwrap-machine-word(y); primitive-machine-word-unsigned-less-than?(raw-x, raw-y) end function machine-word-unsigned-less-than?; ////////////////////////////////////////////////////////////////////////////// // Signal overflow // We use to signal this condition but override // the default message to supply a more detailed explanation of the cause. /// This function is also invoked by the low-level runtime in response to a hardware exception define function machine-word-overflow () error(make(, format-string: "Integer overflow: The result of the last operation is " "too large for this integer representation.")) end function machine-word-overflow; define macro signal-overflow-definer { define signal-overflow ?:name } => { define inline-only function ?name (x :: , y :: ) => (result :: ) let raw-x :: = primitive-unwrap-machine-word(x); let raw-y :: = primitive-unwrap-machine-word(y); primitive-wrap-machine-word("primitive-" ## ?name(raw-x, raw-y)) end function ?name } end macro; define signal-overflow machine-word-add-signal-overflow; define signal-overflow machine-word-subtract-signal-overflow; define signal-overflow machine-word-multiply-signal-overflow; define macro signal-overflow-sign-adjust-definer { define signal-overflow-sign-adjust ?:name } => { define inline-only function ?name (x :: ) => (result :: ) let raw-x :: = primitive-unwrap-machine-word(x); primitive-wrap-machine-word("primitive-" ## ?name(raw-x)) end function ?name } end macro; define signal-overflow-sign-adjust machine-word-negative-signal-overflow; define signal-overflow-sign-adjust machine-word-abs-signal-overflow; define inline-only function machine-word-shift-left-signal-overflow (x :: , count :: ) => (result :: ) let raw-x :: = primitive-unwrap-machine-word(x); let raw-count :: = integer-as-raw(count); primitive-wrap-machine-word (primitive-machine-word-shift-left-signal-overflow(raw-x, raw-count)) end function machine-word-shift-left-signal-overflow; ////////////////////////////////////////////////////////////////////////////// // Double division define macro double-division-definer { define double-division ?:name } => { define inline-only function ?name (dividend-low :: , dividend-high :: , divisor :: ) => (quotient :: , remainder :: ) let raw-low :: = primitive-unwrap-machine-word(dividend-low); let raw-high :: = primitive-unwrap-machine-word(dividend-high); let raw-div :: = primitive-unwrap-machine-word(divisor); let (quotient :: , remainder :: ) = "primitive-" ## ?name(raw-low, raw-high, raw-div); values(primitive-wrap-machine-word(quotient), primitive-wrap-machine-word(remainder)) end function ?name } end macro; define double-division machine-word-double-floor/; define double-division machine-word-double-ceiling/; define double-division machine-word-double-round/; define double-division machine-word-double-truncate/; define double-division machine-word-double-divide; ////////////////////////////////////////////////////////////////////////////// // Unsigned double define inline-only function machine-word-unsigned-double-divide (dividend-low :: , dividend-high :: , divisor :: ) => (quotient :: , remainder :: ) let raw-low :: = primitive-unwrap-machine-word(dividend-low); let raw-high :: = primitive-unwrap-machine-word(dividend-high); let raw-div :: = primitive-unwrap-machine-word(divisor); let (quotient :: , remainder :: ) = primitive-machine-word-unsigned-double-divide(raw-low, raw-high, raw-div); values(primitive-wrap-machine-word(quotient), primitive-wrap-machine-word(remainder)) end function machine-word-unsigned-double-divide; define macro unsigned-double-shift-definer { define unsigned-double-shift ?:name } => { define inline-only function ?name (low :: , high :: , count :: ) => (low :: , high :: ) let raw-low :: = primitive-unwrap-machine-word(low); let raw-high :: = primitive-unwrap-machine-word(high); let raw-count :: = integer-as-raw(count); let (low :: , high :: ) = "primitive-" ## ?name(raw-low, raw-high, raw-count); values(primitive-wrap-machine-word(low), primitive-wrap-machine-word(high)) end function ?name } end macro; define unsigned-double-shift machine-word-unsigned-double-shift-left; define unsigned-double-shift machine-word-unsigned-double-shift-right;