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.