ILMs

Overview

ILMs are the internal representation of a subprogram’s executable statements created by the Semantic Analyzer and translated into the second internal representation, ILI, by the Expander.

An ILM consists of an opcode followed by a number of operands which depends on the opcode, or may also vary for a given opcode. The opcode and operands are of type short int. Typical opcodes are arithmetic operations, variable loads and stores, conditional branches, function call, etc. ILM opcodes are non-zero positive integers referenced via macros whose names begin with IM\_. These macros are defined in the include file ilmtp.n.

The ILMs are grouped into blocks, each of which is a sequential set of words. A block generally contains the ILMs generated for a single statement. For C, compound and loop statements may generate more than one block, and for Fortran, I/O statements with implied DO loops generate more than one block. Each block begins with a BOS ILM specifying (1) the source line number of the statement, and (2) the number of words making up this block.

A BOS may never appear within a block.

ILM operands may be links to other ILMs, but only preceding ILMs in the same block. Links are integers relative to the beginning of the block which contains them. The links may point over a branch, label, or function call ILM. An ILM may be pointed to by more than one other ILM, but this is not typical (can happen for uses of '++' or '--' operator, or for statement function expansion).

ILM operands may also be symbol table pointers or short constants.

The Semantic Analyzer buffers one block of ILMs at a time in a dynamic storage area. When a block is completed it is written out to a temporary file in binary format (by routine wrilms). If the -nocode flag is specified writing of the file is inhibited. At this point also, a debug dump of the ILM block is performed if requested by the compiler maintainer.

ILM Attributes and Templates

Associated with each ILM opcode is a set of information used by the Expander to translate the ILMs into ILI. This information is defined symbolically in a file which is processed by the utility program ILMTP, described below, which creates the declaration and data definition files needed to access the information. See Appendix IV for the definition of the current ILMs and their attributes and templates.

ILM Attributes

The attributes for a given ILM opcode consist of the following structure of information:

struct  {
  char \*name;
  char type;
  short int oprs;
  INT oprflag;
  short int temps;
  short int template;
  short int ilict;
};
name

pointer to null terminated character string for the ILM name. This is needed for the ILM debug dump only.

type

type of the ILM. The allowed values are: ‘a’ arithmetic ‘b’ branch ‘c’ constant ‘l’ load ‘s’ store ‘r’ reference ‘p’ procedure ‘m’ miscellaneous

oprs

number of operands. For ILMs which take a variable number of operands, this is the number of operands in the “fixed length part”. The number of operands for a given occurrence of such an ILM is equal to this value plus the value of the first operand.

oprflag

Bit map defining the type of each operand, and the attributes of the ILM:

31

30

29

3:2

1:0

_

spec

trm

var

&…

op2

op1

_

opi

2 bit fields corresponding to the ILM operands in reverse order. The values (macros defined in include file ilm.h) are:

OPR_LNK

this operand is a link to another ILM.

OPR_SYM

this operand is a symbol table pointer.

OPR_STC

this operand is a short constant.

OPR_N

.fi this operand specifies the number of operands in the .q “variable length part” . Only the first operand of an ILM is allowed this value.

spec

1 bit field which is set if this is a “special case” ILM, i.e. one whose expansion into ILI is not purely table driven.

trm

1 bit field which is set if the ILM is a terminal ILM (i.e., a store, branch, etc.).

var

1 bit field which is set if the ILM has a variable number of operands. For these ILMs, operand one contains the number of variable operands.

temps

number of temporaries used in the template for this ILM.

template

index into the ILM template array for this ILM (see below).

ilict

number of ILI in the template.

ILM Templates

An ILM template defines the sequence of one or more ILI into which ILMs of a given opcode are translated by the Expander. An ILM template consists of one or more “ILI specifications” which are stored sequentially in the ILM template array (c ilmtp). Each ILI specification has the form:

_

iliopc

result

opr1

opr2

&…

oprn

_

iliopc

ILI operation code (refer to appendix V).

result

index into the ILM operand array which defines for the Expander how the ILI created for the ILI specification is to be handled, i.e., if the ILI is the “result” of the ILM, if the ILI is assigned to a template temporary, etc. A value of 0 indicates that there is no result.

opri

index into the ILM operand array which defines for the Expander how the corresponding ILI operand is to be constructed. The number of these entries depends on iliopc (the ILI attribute structure must be referenced - see section 13). A value of 0 indicates that there is no operand.

The operand array (c ilmopnd) consists of a common pool of operand definitions, each of which defines how an ILI operand is constructed or how the result of an ILI is to be processed by the Expander. Each definition has the form:

_

type

aux

_

where each field is type INT.

result and each opri are indices (subscripts) into this array. The first entry of ilmopnd (i.e., a subscript value of 0) consists of a single value (0). Each result/operand type has a macro definition whose name begins with ILMO\_. These macros are defined in the include file “ilm.h”.

Result Definition:

type

aux

meaning

_

ILMO_R

N/A

ILI is the single template result

ILMO_RR

N/A

ILI is the real template result (for complex)

ILMO_IR

N/A

ILI is the imaginary template result

ILMO_T

n

.fi ILI is the template temporary result .i n (n >= 1)

Operand Definition:

type

aux

meaning

_

ILMO_P

n

ILI pointed to by the nth ILM operand

ILMO_RP

n

.fi ILI pointed to by the .i n th ILM operand is the real part of a complex operand

ILMO_IP

n

.fi ILI pointed to by the .i n th ILM operand is the imaginary part of a complex

ILMO_T

n

Template temporary n

ILMO_V

n

.fi Value of the .i n th ILM operand (a ST pointer)

ILMO_SZ

n

.fi Value of the .i n th ILM operand which locates a data type entry. The data type entry will be used to determine the size of an item.

ILMO_IV

n

Immediate value n

ILMO_ISYM

n

.fi Integer literal .i n is an index into the ILM auxiliary array which is the text of the literal (in this case, an integer) used to form a symbol table entry (in this case, an integer constant)

ILMO_RSYM

n

Real literal (real constant)

ILMO_XRSYM

n

.fi Hexadecimal literal which represents the value of a real constant.

ILMO_DSYM

n

Double literal (double constant)

ILMO_XDSYM

n

.fi Two hexadecimal literals separated by a a comma which represents the value of a double constant. The first literal is the most significant part; the second literal is the least signifcant part.

ILMO_ESYM

n

External literal (proc symbol)

ILMO_DR

n

.fi Integer register for intrinsic argument .i n . A value of -1 indicates that there is not a register associated with the ILI. Note that for this operand and the remaining register argument operands, the value .i n represents argument .i n+1 and is mapped to the appropriate target register.

ILMO_AR

n

Address register n.

ILMO_SP

n

Single precision register n.

ILMO_DP

n

Double precision register n.

ILMO_ISP

n

Imaginary single precision register n.

ILMO_IDP

n

Imaginary double precision register n.

The ILM auxiliary array (c ilmaux) consists of a sequence of character strings representing the text of the literals. Each string is null terminated (i.e., it is a normal C character string) and will be used to form the “value” of a symbol table entry.

Auxiliary Data Structures - Switch Lists (C only)

Switch Lists are created by the Semantic Analyzer as it processes switch (case) statements and their embedded case and default (otherwise) labels. A switch list is used by the Expander to generate ILI for a switch statement when the SWITCH ILM which points to the switch list is processed.

Switch lists are stored in a single dynamic storage block. All pointers to switch list elements are relative (c short int) values. Each list consists of a header record followed by a linked list of case records which define case value, label pairs. The elements of this list are ordered by the case value, not by the order in which they appeared in the source program. There is no list element for a default label. Instead, the list header contains the default label (if none was specified by the user, the break label is used).

The same structure is used for list headers and list elements:

struct {
    INT   val;
    short clabel;
    short next;
};

For list headers:

val

not used.

clabel

symbol table pointer for the default label.

next

pointer to first list element (0 if no cases).

For list elements:

val

integer case value.

clabel

.fi case label (compiler created symbol allocated by the Semantic Analyzer).

next

.fi pointer to next list element (a value of 0 indicates the end of the list).

ILM Template Utility (ILMTP)

ILMTP reads the file which defines the ILM opcodes and their attributes and templates, and writes the C declaration and definition files needed to reference the information within the compiler. ILMTP must be re-run whenever an ILM opcode is deleted or added, or its attributes or template modified. Certain changes to the ILI definition file (section 13) also require that ILMTP be run (see note below).

Inputs

ILMTP reads two input files:

  1. ILM definition file. Defines the ILM opcodes, their attributes and templates. This file is in nroff format and is used to create appendix IV of this document. It contains three types of lines processed by ILMTP: ILM definition line of the form:

    .IL name type[\*] opr1 opr2 ... oprn[\* | +]
    
    
    
    
    
    name
       name of the ILM.
    
    
    
    type
       type of the ILM.  Must be one of "arth", "branch", "ref"
       "const", "load", "store", "proc", or "misc".
    
    
    
    opri
       operand type.  This must be one of "lnk", "sym",
       "stc", or "n".  "n" is only allowed for the
       first operand.  "n" indicates that this is a
       variable length ILM and is allowed only if the last
       operand if followed immediately by "\*" or "+".
       This means that the last operand specifier
       defines the type of the variable length part
       operand; "\*" means the variable length part
       consists of 0 or more operands, and "+" means
       that it must contain at least one operand.
       The occurrence of n as the first operand will set the "var"
       attribute.
    
    
    
    
       ILM attribute line. Defines the attributes of the ILM opcodes.
       The appearance of this line is optional; it, however, must precede
       the ILI specification line(s) if it is used. The line is of the form:
    
       .. code-block:: none
    
          .AT followed by zero or more occurrences of <attribute>
    
       where <attribute> is one of the following:
    
    
    
    spec
       The ILM is to be special cased by the Expander.
    
    
    
    trm
       The ILM is a terminal ILM.
    
    
    
    
       ILI specification line.  Zero or more of these follow each
       ILM definition line and together they specify the ILM template.
       The line is of the form:
    
       .. code-block:: none
    
              .OP ili result opr1 opr2 ... oprn
    
    
    
    
    ili
       ILI opcode
    
    
    
    result
       result of the ILI; one of:
    
       +----+------------------+
       |null|no result         |
       +----+------------------+
       |r   |single result     |
       +----+------------------+
       |rr  |real result       |
       +----+------------------+
       |ir  |imaginary result  |
       +----+------------------+
       |tn  |temporary result n|
       +----+------------------+
    
    
    
    
    opri
       operand of the ILI; one of:
    
       +------+-----------------------------------------+
       |null  |no operand                               |
       +------+-----------------------------------------+
       |pn    |pointer from the nth operand of the ILM  |
       +------+-----------------------------------------+
       |rpn   |real pointer n                           |
       +------+-----------------------------------------+
       |ipn   |imaginary pointer n                      |
       +------+-----------------------------------------+
       |tn    |temporary n                              |
       +------+-----------------------------------------+
       |vn    |value in the nth operand of the ILM which|
       |      |is a ST pointer                          |
       +------+-----------------------------------------+
       |szn   |value in the nth operand of the ILM which|
       |      |is a DT pointer whose size is needed     |
       +------+-----------------------------------------+
       |ivn   |immediate value n                        |
       +------+-----------------------------------------+
       |=i'str|integer literal (str is the text of the  |
       |      |literal)                                 |
       +------+-----------------------------------------+
       |=r'str|real literal                             |
       +------+-----------------------------------------+
       |=d'str|double literal                           |
       +------+-----------------------------------------+
       |=e'str|external literal                         |
       +------+-----------------------------------------+
       |dr(n) |data register n                          |
       +------+-----------------------------------------+
       |ar(n) |address register n                       |
       +------+-----------------------------------------+
       |sp(n) |single precision regsiter n              |
       +------+-----------------------------------------+
       |dp(n) |double precision register n              |
       +------+-----------------------------------------+
    
    1. ILI Definition File. This file is the primary input to the ILITP utility program and so is described in section 13. It is read by ILMTP in order to extract just the following information: the name and opcode number of each ILI, and the number of operands of each ILI. Note that if any changes to the ILI Definition File affect these quantities, ILMTP must be re-run.

Outputs

ILMTP produces two output files:

  1. ilmtpdf.h — contains the C data definitions and initialization code for the ILM templates and attributes.

  2. ilmtp.h — contains the C constant symbol definitions for the ILM opcodes

Miscellaneous Information

The file ilm.h contains various macro definitions which define the possible values of the ILM attributes. This file also contains the declarations and typedefs for the ILM and ILM-related data structures (i.e., ILMINFO, the ILM templates, etc.).