The methodology for creating this guide is as important as its unfinished contents. This guide is produced by reverse-engineering, that is to say, by examining the output of "unicon -c". It potentially needs to be updated whenever the Unicon version changes.
| ucode | comment |
|---|---|
version U12.1.00 uid u1.u1-1681329218-0 impl local global 1 0,000005,main,0 ^L |
ucode version number, always (for now) U12.1.00 unique identifier: uid<tab>filename.u1-randomnumber-0 what to do with undeclared variables: impl<tab>local global region: global<tab>N globals, one per line: index,flags,name,0 single form-feed character on a line by itself |
local with
operands consisting of its index, flags, and the declared variable name.
Literal constants are similarly comprised of an index, then flags, followed
by the literal constant data.
The flags are a string of six octal format characters containing ASCII 0-7 and denoting three bits per character for a total of 18 bits, of which 13 are used. The same flags format is shared by variables and literals, so many of the flag bits are mutually exclusive. From unicon/src/icont/link.h, the definitions of the bits, which may be tested for independently, are:
| Flag Name | Octal Value | Description |
|---|---|---|
| F_Global | 01 | variable declared global externally |
| F_Unref | 02 | procedure is unreferenced |
| F_Proc | 04 | procedure |
| F_Record | 010 | record |
| F_Dynamic | 020 | variable declared local dynamic |
| F_Static | 040 | variable declared local static |
| F_Builtin | 0100 | identifier refers to built-in procedure |
| F_ImpError | 0400 | procedure has default error |
| F_Argument | 01000 | variable is a formal parameter |
| F_IntLit | 02000 | literal is an integer |
| F_RealLit | 04000 | literal is a real |
| F_StrLit | 010000 | literal is a string |
| F_CsetLit | 020000 | literal is a cset |
Lines are indented by a tab character except for the header line and labels. After the mnemonic, lines that contain operands have a tab character and then one or more operands separated by commas. I expect that TAB characters (control-I) may not be substituted using spaces. An example of this format is show below.
| Ucode | comment |
|---|---|
proc name local 0,flags,varname ... local n,flags,varname con 0,flags,... ... con m,flags,... declend ...code instructions end |
see intermediate mapping section for flags examples see intermediate mapping section for constant formats |
See Appendices B and C of The Implementation of Icon and Unicon for more complete information. Ask the instructor as needed.
| intermediate code instruction |
ucode equivalent | comment | |||||
|---|---|---|---|---|---|---|---|
| global | global N | N = # of globals | |||||
| global x | i,000001,x,0 | index#,flagbits,varname,0 | |||||
| const 42 | i,002000,2,42 | index#,flagbits,#digits,digits | |||||
| const 3.14 | i,004000,3.14 | index#,flagbits,real# | |||||
| const "hello" | i,010000,5,150,145,154,154,157 | index#,flagbits,#chars,octal1,...,octaln | |||||
|
x := y + z (global variables in slots i, j, k) |
mark Ln pnull var ix pnull var jy var kz plus asgn unmark lab Ln | stack machine; push slots for results, operands and then do instructions. Locals and globals are always using a local index #; the linker sorts out who is actually global. | |||||
| local x |
local i,000000,varname | ||||||
|
x := y + z (local variables) |
mark Ln pnull var ix pnull var jy var kz plus asgn unmark lab Ln | Same as for globals. Code generated does not depend on scope/region... | |||||
| x := y / z |
mark Ln pnull var ix pnull var jy var kz div asgn unmark lab Ln | Same as for other binary operators, except the div instruction | |||||
|
x := - y |
mark Ln pnull var ix pnull var jy neg asgn unmark lab Ln | ||||||
|
x := y |
mark Ln pnull var ix var jy asgn unmark lab Ln | ||||||
| x := &y (y global) | n/a | see instructions used e.g. for lists and tables | |||||
| x := &y (y local) | n/a | see instructions used e.g. for lists and tables | |||||
| x := *y | n/a | see instructions used e.g. for lists and tables | |||||
| *x := y | n/a | see instructions used e.g. for lists and tables | |||||
| goto L | goto L
| beware marks and unmarks. L4 might start with an unmark. goto instruction might be preceded by pnull | |||||
|
if x < y then goto Lm |
mark Ln mark0 pnull var 1 var 0 numgt unmark unmark unmark pnull goto Lm unmark lab Ln | Full set of instructions for comparison operators. Beware numbers of marks/unmarks. | |||||
|
if x then goto Lm |
mark Ln mark0 pnull var 0 int 1 numeq unmark unmark unmark pnull goto Lm unmark lab Ln | ||||||
| if !x then goto L |
cmpq $0, -8(%rbp)
|
Why not:cmpq $0, -8(%rbp)
| |||||
| param x |
| Calculate what parameter # you are by counting how many instructions in the linked list until you get to the CALL instruction. | |||||
| call p,n,x | If call is to a member function, I hope you remembered to insert/push "self" object as first parameter for method invocation | ||||||
| return x |
mark Ln var ix pret lab Ln | ||||||
| return |
mark Ln pnull pret lab Ln | ||||||
| proc x,n1,n2 |
i,000005,x,0 # in globals ... proc x ...locals declend ...code pfail end | ||||||
| label Ln | lab Ln |