IPL: The Icon Program Library Comment Domumentaion

# The Icon Program Libary

    from codegen

    from ststructs.mh

    Variable was directly stack allocated

    Array is contiguously allocated.

    Imported into nested scope

    Variable is referenced other than as

    argument to V or :

    With the -R option, the -G code generator keeps

    identifier bindings or variables in v. registers:

    displacement is v. register number

    r.h.s always evaluates to integer constant decl_const_val:

    RIC (Russell Intermediate Code) Op codes

    The first group has a single string argument

    branch unconditionally

    branch if value in TL is true.

    branch if value in TL is false.

    call routine with given label

    Needs to do any cleanup (e.g. stack pops)

    necessitated by the preceding ARG instr that

    passed the activation record pointer.

    attach the given label to the next instruction

    declare the label to be external

    All labels that need to be known to the

    outside are marked in this way. All labels

    not beginning with an 'L' are intended to be

    unique, and thus may be made globally visible.

    supply a label argument to immediately

    following instruction

    begin named function

    function temporaries may be reserved on the

    stack at this point

    FP should be set to point to one below return

    address. AR should be set to first (and only)

    argument. Other locations are set explicitly.

    Locations (incl. AR) are implicitly saved

    during a procedure call.

    trace function entry

    trace function exit

    record function entry for profiling

    character string data. A label for the

    location of the data may be supplied by a

    preceding LBA instruction OBSOLETE

    branch to error routine with indicated label

    Arguments may have been pushed.

    begin short function. Identical to BFN,

    except that AR should neither be set, nor does

    the old value need to be saved.

    Arguments to BSF functions are passed

    individually using ARG, rather than passing a

    a single argument containing the activation

    record. If the name of the function does not

    start with Ffn, the generated function must be

    C callable. (Typically it will be, in any

    case.)

    declared by the immediately following DCL

    Generate double precision floating point data.

    May be labelled with an LBA instruction.

    The argument is actually a string representing

    representing a floating point constant.

    Such data is read-only.

    Analogous to FDT, but for single precision

    constants.

    The remainder has up to 3 integer arguments. Unless otherwise

    specified, they refer to temporary locations (virtual

    registers). An offset is a signed integer value.

    An object is considered accessible only if there is an

    accessible pointer to its beginning.

    Pointers in any active temporary or on the stack are accessible

    args

    loc type -- declare temporary location

    (i.e. virtual register)

    The following types are allowed:

    32 bit integer

    DCL_ADDR and DCL_INT, are assumed to be the

    same size. The distinction is only a hint

    to the machine code generator.

    DCL_FLOAT is unlikely to be used in the

    near future.

    In the following, size is a location:

    loc -- free temporary location

    If applied to a predefined location, this

    constitutes a declaration that the value it

    contains is dead at this point.

    Duplicate UDC's for the same location may

    occasionally appear. All but the first can be

    safely ignored.

    size loc -- loc := ptr to new heap object

    i loc -- Get the ith argument (passed with

    ARG) into loc

    size -- allocate new stack object containing

    pointer data

    Both ALS and ALH are assumed to clear the

    allocated space. This is necessary only for

    garbage collection, and may frequently be

    eliminated by an optimizer

    index offset loc -- loc := index[offset]

    index offset loc -- index[offset] := loc

    index offset -- jsr index[offset]

    Needs cleanup similar to CLL

    signed_value loc -- loc := signed_value

    -- return from function w/ value at loc RL

    loc -- load value of label provided

    by immediately preceding LBA instruction

    The label must have been previously defined.

    loc1 loc2 -- loc2 := loc1

    arg put_fn -- save passed argument for trace

    loc -- push contents of loc onto stack

    equivalent to ALS 1; STI SP, 0, loc

    $define MVI 34 loc1 loc2 -- *loc2++ := *loc1++

    loc1 offset loc2 -- loc2 := &loc1[offset]

    Add a (word) offset to a pointer value

    Unlike LDI and STI, offset here is a location

    nargs -- Call to a non-Russell routine or a BSF

    style Russell routine. Nargs

    is an integer. The routine name is given by

    are supplied in reverse order by prior

    ARG instructions.

    size loc -- loc := ptr to new atomic heap

    object. Object should never contain pointer

    data.

    kind arg1 arg2 -- Code generator hint.

    n -- The next n instructions perform

    runtime checks, and may be discarded at

    suitably high levels of optimization.

    The following ARG instruction refers to a

    pointer to an object that may be on the

    heap. The called procedure does not

    preserve references to this object. Thus

    the ARG instruction may be disregarded for

    purposes of static ref. counting

    size atom -- (size is a constant). The

    following procedure call (CLC, CLL, CLI)

    returns a new object of the indicated

    size. If size is != 0 the object may

    be deallocated by attaching it directly

    to the free list of the indicated size.

    If size is = 0, the size of the object

    is unknown, and the object could be

    statically allocated; rfree should be

    called to release it.

    Atom is either 0 or 1, and

    specifies whether the allocated object is

    atomic, and thus should be returned to the

    atomic object free list.

    loc size -- Indicates that

    the object pointed to by loc may be freed.

    This type of hint is inserted by the

    static reference counter for the benefit

    of the code generator.

    A negative size indicates the object is

    atomic; a positive size means composite,

    and a 0 size means unknown.

    Size is a constant, not a location.

    The following CLL or CLI instruction

    does not result in a saved continuation.

    Thus the reference counts of objects

    pointed to only by virtual registers

    is unchanged across the call.

    (This is always the case for CLC calls.)

    loc -- The following STI instruction

    should store the size of loc if it's known

    that loc has exactly one reference, and 0

    otherwise. Loc contains a pointer to a

    composite object.

    Analogous to NP, but a single reference is

    preserved (passed through) as the function

    result.

    loc -- The value in loc will not be used

    again. (The location itself may be reused.

    Thus UDC would be inappropriate.)

    GF is about to be updated, or AR is about

    to be updated inside a BSF function.

    Such a hint always precedes the first such

    update in a routine.

    loc -- The value in loc should be viewed

    as live up to this point. Such a hint is

    included whenever a location (other than

    GF and AR) could appear to be dead, but a

    derived pointer is not. A value in such a

    location needs to be retained, so as not

    to confuse the garbage collector.

    We do not generate such HINTs if it is

    known that the value in question is also

    stored in an accessible memory location.

    Similarly, we do not generate such a HINT

    if the derived pointer is only implicit

    in an LDI or STI instruction.

    Defines the type of the following item

    declared by an EXT. All EXTs that do not

    refer to functions are preceded by such a

    hint. The second argument is a type

    specifier, as for the DCL instruction.

    The following allocation instruction may

    be implemented as a stack allocation.

    This is used only if the comipler is not

    allowed to generate ALS instructions (-f

    or -F flag). Each allocation instruction

    preceded by a HINT ONS is eventually

    followed by a corresponding HINT ONS;

    HINT DEA sequence. All such pairs are

    properly nested. There are no branches

    into or our of such a pair.

    n loc -- Pass loc as the nth argument to CLC

    ARG instructions always occur in reverse order,

    with highest numbered argument first. The

    lowest numbered argument is numbered 1.

    Also used to pass the activation record pointer

    through CLL and CLI calls.

    MAY reserve space on the stack.

    Integer operations

    op1 op2 result -- result := (int)op1 + (int)op2

    op1 op2 result -- result := (int)op1 - (int)op2

    op1 op2 result -- result := (int)op1 * (int)op2

    op1 op2 result -- result := (int)op1 / (int)op2

    op result -- result := -op

    data -- generate integer data. May be labeled

    with an LBA

    Consecutive IDTs w/o intervening LBAs generate

    consecutive data.

    Data is read-only.

    op1 op2 result -- result := (int)op1 = (int)op2

    op1 op2 result -- result := (int)op1 < (int)op2

    op1 op2 result -- result := (int)op1 > (int)op2

    op1 op2 result -- result := (int)op1 != (int)op2

    op1 op2 result -- result := (int)op1 <= (int)op2

    op1 op2 result -- result := (int)op1 >= (int)op2

    op1 op2 result -- result := arith_shift(op1, op2)

    op1 result -- result := abs(op1)

    Boolean operations

    loc -- load the constant true into the

    indicated location.

    loc -- load the constant false into the

    indicated location.

    The following instructions are assumed to work on

    both Booleans and bit vectors:

    op1 op2 result -- result := op1 & op2

    op1 op2 result -- result := op1 | op2

    The following applies only to Booleans:

    op result -- result := ~ op

    String operations

    loc -- put a pointer to the string given by the

    preceding LBA instruction into loc

    index offset loc -- loc := index[offset]

    Differs from LDI in that offset is a virtual

    register (location) and it is a BYTE rather than

    word displacement from index. Used to access

    individual characters in a string.

    Operations on single precision floating point numbers

    op1 op2 result -- result := (float)op1 + (float)op2

    op1 op2 result -- result := (float)op1 - (float)op2

    op1 op2 result -- result := (float)op1 * (float)op2

    op1 op2 result -- result := (float)op1 / (float)op2

    op result -- result := - (float) op

    op1 result -- result := (int) x s.t.

    2 **(x-1) <= op1 < 2**x

    op1 op2 result -- result := (float)op1 = (float)op2

    op1 op2 result -- result := (float)op1 < (float)op2

    op1 op2 result -- result := (float)op1 > (float)op2

    op1 op2 result -- result := (float)op1 != (float)op2

    op1 op2 result -- result := (float)op1 <= (float)op2

    op1 op2 result -- result := (float)op1 >= (float)op2

    op1 op2 result -- result := (float)op1 * 2** (int)op2

    predefined locations

    activation record pointer

    stack pointer

    pointer to global act. rec.

    explicitly saved and restored by

    Thus it can easily be assigned to a

    fixed register.

    location containing "undefined" value

    value sink, nothing comes out ...

    An instruction using SK as

    destination or an STI SK,... is a

    noop

    location for function result

    capable of holding max size object

    0x30000000

    result of operation. In-line code only

    Can't be legitimate operand to anything

    but LDN

    Location tested in conditional branches

    Dead after first reference.

    always 0

    always 1

    always 2

    always 3

    always 4

    T1 and T2 are short term temporaries. They should be

    used only in fixed code sequences, not involving

    arbitrary embedded code. T1 is mapped to the same

    location as RL, and may thus conflict with RS in

    inline code sequences. T2 will never be specified as

    the result location for an inline code sequence.

    T1 is assumed to be predeclared. T2 is not treated

    specially by the final code generator.

    Since T1 and RL are the same, and will presumably be

    mapped to the location used for function results, we

    assume that T1 may be clobbered by ALA and ALH.

    Note: All general locations are expected to be saved and

    restored on procedure call.

    Activation record layout (all parts optional):

    0: static link

    1: 1st arg

    ...

    locals

    Function object layout:

    0: size

    1: ep

    2: ip

    Declarations for precedence levels

    no 0 in list so 1 added

    precedence levels for right associative operators */

    for grammar.y

    0x7fff

    moved from grammar.icn

    following from pass1/parser/rcs.h

    will have to be changed alltogether!

    The following are bit vectors defining which characters may legally */

    appear inside quoted identifiers. The msb of each word corresponds */

    to the character with smallest ascii code. */

    Note the machine and character set dependence of this whole scheme. */

    From scan.h

    * character classes

    */

    From precedence.h

    * Declarations for precedence levels

    */

    $define NLEVELS 14

    $define INFINITE (NLEVELS+1)

    for sigio

    from pass4

    Success indication returned by findsig

    Special signature field values

    FROM stplinks.mh

    define SZSTANDARDPREFIX 4

    used to be 5, before we dropped refcount */

    Variable was directly stack allocated

    Array is contiguously allocated.

    Imported into nested scope

    Variable is referenced other than as

    argument to V or :=

    With the -R option, the -G code generator keeps

    identifier bindings or variables in v. registers:

    displacement is v. register number

    r.h.s always evaluates to integer constant decl_const_val:

    parameter.  NIL indicates no call

    found so far. MULTIPLE_DEFS

    indicates that different arguments

    are passe, or we don't know the

    identity of the argument.

    MULTIPLE_TP_DEFS indicates that

    different arguments are passed,

    but they are all types with

    standard := and V operations.

    Gives list of quoted characters with

    default signatures. Also used as a

    type signature component.

    Assumes ASCII, 32 bits per word

    There is a sourrounding loop with no

    define INSIDE_LOOP       1

    intervening blocks or function

    abstractions.

    Also set if there is a possibility

    that the block may be reexecuted

    without leaving the surrounding

    function due to Call/cc calls.

    A closure value is built inside the

    block.

    There may be an embedded Call/cc

    call.

    We need an a.r. if this is inside a

    define REQUIRES_AR       8

    loop, and it either the block builds

    a closure, or there is a Call/cc

    call embedded in the block.

    These imply that it is not safe to

    promote bindings to surrounding

    function activation record.

    It is known that there is no

    explicit loop between this block

    and the surrounding function

    construction.  Implies not

    INSIDE_LOOP, but can be computed

    much earlier.

    Static link not needed,

    no "complicated" constructs,

    no accesses through AR.

    No calls to an output routine

    Environment can't be saved by

    call/cc call.  This implies

    that it's safe to allocate

    variables directly on the stack

    There are no nested fn constrs.

    that could conceivably be

    exported.

    Thus it is safe to copy id

    bindings into the closure itself

    Closure must be explicitly represented

    Nonlocal bindings WILL BE copied to

    closure. Requires that NO_CONSTR

    holds, that there aren't too many

    non-locals, that the closure needs

    to be explicitly built, that

    none of the non-locals constitute

    forward references, and that there

    are no calls to the procedure that

    could otherwise bypass evaluation

    of the operator.

    All nested fn constructions that require

    a closure copy identifier bindings into

    the closure itself.  Thus it is

    automatically safe to allocate

    activation record on the stack.

    Known to call itself directly and

    tail-recursively.

    There is a direct call to this

    procedure that does not require

    an explicit closure.

    Procedure may indirect through

    static link.  Thus it better be

    there.  (Accesses through AR are

    possible even if SL_ACC is false)

    Procedure contains a nested block that

    requires its own activation record.