• No results found

A Formally Verified Register Allocation Framework

N/A
N/A
Protected

Academic year: 2021

Share "A Formally Verified Register Allocation Framework"

Copied!
17
0
0

Loading.... (view fulltext now)

Full text

(1)

A Formally Veried Register Allocation Framework Kent D. Lee 1 Computer Science Luther College

Decorah, IowaUSA

Abstract

Whenusingformalmethodstogeneratecompilersitisdesirableforalllevelsofthe

compilerto beformallyspecied. Typically,registerallocationhasbeenthoughtto

be equivalent to graph coloring. Since graph coloring is NP-Complete most

algo-rithms for register allocation have been ad-hoc. This paperpresents a framework

for register allocation that has been formally veried using an inductive theorem

prover.

1 Introduction

Generating compilers from formal language descriptions means targeting a

specic machine architecture. Because of the nature of most high-level

lan-guages, stack-based target architectures are easy architectures for which to

generate code. However, most new architectures are RISC-based and

there-fore require operands tobe in registers.

To ease the assignment of operands to registers, register allocation has

typicallybeen performedby assumingan unlimitedsupply of symbolic

regis-ters. Once code generation is completed, ad-hoc methods are used to assign

these symbolic registers to the actual, physical registers of the machine [2].

This processresembles graphcoloringwhichisknown tobeNP-Complete [3].

Therefore it has been thought that register allocation is an NP-Complete

problem and hence mustbe done by ad-hocmethods.

This paperpresents analgorithm forregister allocationthat is not NP or

NP-Complete. In fact, it is O(jVj 2

) where V is the set of symbolic registers

being allocated.

The paper begins by presenting an example of a small program to

moti-vate the discussion of register allocation. Then, a formal description of that

1

Email: [email protected]

c

(2)

program using Action Semantics is presented. An assembly language

imple-mentationof the programisprovided aswell,showing howsymbolicregisters

are usedinthe targetcode. Next, aproperty ofregisterinterference graphsis

presented thatallows them tobeminimallycoloredin polynomialtime anda

proofofcorrectness isprovided. A frameworkforregisterallocation,basedon

the proofispresentedinthenext section. Anexampleofusingthe framework

togenerate code ispresented, andnally,the workis comparedtootherwork

on registerallocation. 2 A Motivating Example let fun f(x)=x+5 val i = ref 0 in i:=input(); output(1 + ((2 + 3) + f(!i))) end

Fig.1. a Smallprogram

Consider the program written using a small subset of ML in gure 1.

This language will be referred to as the Small language. Given an Action

Semantics [8] description for Small [5], the program's corresponding action

might look like the one given ingure 10.

Typically, formal semantic descriptions of programs are not directly

suit-able for code generation in low-level languages [6]. While Action Semantics

is chosen as the formal method for language description in this paper, the

register allocationframework presented here can beused in any compiler.

Regardless of the chosen formal method for language description,

trans-formationsonthe descriptionare usuallyrequiredtoget the program's

repre-sentationreadyforcode generation. Forinstance,bindingeliminationisoften

performed [9] on actions. Statically known information is usually applied to

the formalnotationtosimplifytheprogramdescription. Somecompilersmay

employpartialevaluationwithrespect tosomeknown (static)information[1]

to simplifythe source program.

Whichever formal language is used, the end result is a transformed

de-scriptionofaprogramthatisinsomewaymoresuitablefortranslationtothe

intended target architecture. In this paper, the action in gure 10 is

trans-formed by removing statically known bindings and by eliminating unneeded

transient values. The resultingaction, along with some sort (i.e. type)

infor-mationispresented ingure11. Theactioningure11isreadytobegiven to

a code generator. In the next section this action is given toa code generator

which must generate instructions involvingregisters toimplementit.

(3)

that resembles postx notation(i.e. operands are evaluated rst, followed by

the operation itself). For instance, the action in gure 11 is in postx form.

Postx actions are described in [6]. Stack machines are designed for postx

evaluation. Howevever, register machines are more prevalent. The register

allocationframework presented here can be used to emulate a stack machine

in registers. This is described in more detail insection 6.

3 Code Generation and Register Allocation

In this sectionthe actioningure11isgiven toacode generator tobe

trans-latedtoatargetarchitecture. SincemosttargetarchitecturestodayareRISC,

and most RISC architectures have very minor dierences (at least at the

in-struction set architecture level) the particular target architecture is

inconse-quential. For purposes of discussion consider the MIPS targetarchitecture.

The action given in gure 11 would typically be given to the code

gener-ator as an abstract syntax tree, so it is possible to think of generating code

incrementally forthis action.

Consider the task of generating code for this subaction:

give2

and then

give3

then

give the sumof the given data

As stated in the introduction, code generation is simpliedif it ispossible to

assume anunlimited supply of symbolicregisters. Symbolicregisters will be

denoted by R0, R1, R2, etc. To generate code for this action the number 2

could be loaded into register R7,3 could be loaded into R8, and R7 and R8

could be added together. This results inthe MIPS code:

li R7,2

li R8,3

add R7,R7,R8

Some things tonote about this code:

The symbolic registers R7 and R8 interfere with each other. That means

they cannot be assignedthe samephysical register.

At the end of this code R8 contains avalue that isn't needed again.

However, R7 contains avalue that willbe used later.

Thisinformationleadstotheconstructionof aregisterinterferencegraph.

Aregisterinterference graphcontainsverticesrepresenting symbolicregisters,

and edges existbetween vertices when their corresponding symbolicregisters

interferewith eachother. The complete MIPScode for thisexample program

(4)

R0

R1

R2

R3

R4

R5

R8

R6

R7

R9

Fig. 2. Theregister interference graphforthe code ingure 12

gure 2.

Tocompletethecodegeneration,thesymbolicregistersneedtobeassigned

tophysicalregistersof the machine. From the registerinterference graphitis

fairlyeasytoconcludethatthreephysicalregisters(inadditiontothephysical

registers alreadybeingused) are required toimplementthe code ingure 12.

In fact,three is the minimum number of registers required given the register

interferencegraphingure2. But,howcanthisbeformallyveriedespecially

when graphs become more complex?

4 Minimally Coloring Register Interference Graphs

In general, graph coloring is known to be NP-Complete. However, if it is

possible to consider only certain types of graphs there may exist polynomial

time algorithms to color them. This is the case with register interference

graphs, at least the type of register interference graphs considered in this

paper. PittmanandPeterssay intheirbookoncompilerdesignthatasimple

demand policyfor allocatingsymbolicregisters seems toworkbest [10]. This

paper helps to formalize that statement. A simple demand based register

allocation policy leads to register interference graphs that adhere to what is

called the lifetime property in graph theory. This property can be formally

stated as follows.

Denition: A simple undirected graph G = (V;E), exhibits the lifetime

propertyi 9:N !V sothat if ((i);(k))2E,then ((i);(j))2E,

i<j <k where is aone-to-one mappingfor N =f1;2;:::;jVjg.

Informally, this property means that there is an ordering of the vertices

suchthatiftwoverticeshaveanedgebetween them,thenallverticesbetween

the rst vertex and the last vertex also have edges to the rst vertex. In

terms ofsymbolicregisters,it meansthatsymbolicregistersare created,they

carry livevalues fora while,and thenthey aren't usedagain. Inother words,

(5)

register allocationpolicy.

Notethatndingthis mapping,ifitexists, foragraphwould take

expo-nentialtime in general,sothis doesnot provide apolynomialtime algorithm

tosolvethe graphcoloringproblemforallgraphsforwhichthe lifetime

prop-ertyholds. However, inthecaseofregisterinterferencegraphs,themappingis

ready toobtain. Itissimplythe orderinwhichthe symbolicregisterswere

re-quested. Forsimplicity,assume fromnowonthat themapping isimplicitly

given asthe indicesofverticesinV forany graphswith thelifetimeproperty,

that is, (i)=v

i

for any v

i 2V.

Proof that the register interference graphs considered here may be

min-imally colored in polynomial time is given below. The following proof was

rst given in a technicalreport authored by Kent Lee and Hantao Zhang [7].

The proof also leads to the framework for register allocation. The algorithm

is implicitly given in the proof of the following theorem, which is done by

induction on the number of verticesin V.

Theorem: A simple undirected graph, G = (V;E) exhibiting the lifetime

property can be minimallycolored intime O(jVj+jEj).

Proof: (by induction on the cardinality of V)

Base case: jVj = 0. Clearly, G can be colored by 0 colors in constant

time.

Inductive case: Assume,bytheinductionhypothesis,forallG=(V;E)

with jVj=n that G can beminimally coloredby k colors in time O(jEj+

jVj)if Gexhibitsthe lifetimeproperty. Consider G 0 =(V [fv n+1 g;E[E 0 ) withjV[fv n+1 gj=n+1whereE 0

containonlytheedgesfromverticesinV

tothe vertex v

n+1

. Wemust consider three cases for G 0

,which issupposed

toexhibit the lifetimeproperty.

Case 1: v

n+1

has less thank neighbors. Clearly,v

n+1

canbecoloredone

of the k colors of G that is not one of the colors of the neighbors of v

n+1 .

The neighbor colors of v

n+1

can be determined by examining the coloring

for G and the neighbors of v

n+1 in E

0

; this can be done in time O(jE 0

j).

Since nonew color is needed, G 0

is stillminimallycolored.

Case 2: v

n+1

haskneighbors. Then,sincethelifetimepropertyholdsfor

G 0 , if (v i ;v n+1 ) 2E 0 then (v i ;v j

) 2E, for i <j <n+1. This means that

v

n+1

forms a (k+1)-clique with its k neighbors in V. But we know from

graph theory that a simple undirected graph with a (k+1)-clique cannot

be colored in less than k +1 colors. Therefore, we have to assign a new

color tov

n+1 ; G

0

is thusstillminimally coloredwith k+1 colors. This can

be done again intime O(jE 0

j).

Case 3: v

n+1

has more than k neighbors. Then there exists at least a

(k+1)-cliqueinG by thesame argumentascase 2. But thismeans thatG

cannotbecoloredwithk colors. This contradictsour induction hypothesis,

sothis case is invalid.

Therefore, G 0

canbeminimallycoloredifGis minimallycolored,and we

(6)

lifetimeproperty maybe minimallycoloredin timeO(jVj+jEj)(assuming

we knowthe mappingof the vertices of V). 2

Theproofgivenhereisthecentralideaexploitedintheframeworkprovided

below. Inaddition,thetechnicalreportwithHantaoZhang[7]containsresults

fromprovingthe sametheoremusing anautomatedinductivetheorem prover

called RRL. The intended property for RRLto prove was: num colors(G)

maxclique(G). Afterproving 8 auxiliarylemmas,RRL was able toprove this

propertyinlessthan30seconds onaHP715 workstation(running theAKCL

lisp). Sinceany graphcannotbecoloredinlesscolorsthan themaximum size

clique, it is safeto conclude that the coloring isindeed minimal.

5 A Framework for Register Allocation

R6

R7

R8

R9

R0

R1

R2

R3

R4

R5

Fig. 3. Theregister interference graphredrawn

Thealgorithmforregisterallocationisbasedonthe simpledemandpolicy

described above. With any algorithmorframework, the rst step is toarrive

atarepresentationof theproblem. Inthis paper, symbolicregisternamesare

R0, R1, R2, etc. Therefore, they may be represented by integers (omitting

the R). Register interference graphs are represented by lists of pairs. Each

pair consists of two integers. The rst integer is the number of the symbolic

register. The second number indicates the physical register to which it is

assigned (i.e. itscolor) or negative one (i.e. -1)if the registeris stillalive.

The list representation is easy to visualize by looking at the graph of

g-ure 2. However, it may help if the graph is redrawn as in gure 3. The list

that represents this graph is given below.

[(9;2);(8;2);(7;1);(6;0);(5;1);(4;0);(3;1);(2;0);(1;1);(0;0)]

Notice that thesecond numberineachpair isnot onlythe colorof the vertex

(i.e. itsassigned physical register)butit isalsothe numberof neighborsthat

preceed itin the graph permutation.

Three functions implement this framework. The functions are written in

Standard ML. The graph is automatically constructed via the use of these

functions.

Therstfunction,createRegingure4,isgivenaregisterinterferencegraph

and createsanew registerbyreturning a newsymobolicregistername and

a new register interference graph that consists of the given graph with the

(7)

val regNum = ref 0;

fun createReg(regList) =

let val reg = !regNum

in

regNum := !regNum+1;

("R"^Int.toString(reg),(re g,~1 )::r egL ist)

end

Fig. 4. The createReg function

exception unknownReg; exception unFreedReg; fun unFreedCount([])=0 | unFreedCount((x,y)::t) = if y = ~1 then 1+unFreedCount(t) else unFreedCount(t) fun freeReg(r, []) = (TextIO.output(TextIO.std Out,

"Freeing non-existant register "^r^"!\n");

raise unknownReg) | freeReg(r, (regNum,color)::t) = if r = "R"^Int.toString(regNum) then (regNum,unFreedCount(t)):: t else if color = ~1 then (TextIO.output(TextIO.stdOu t,

"Illegally freeing register "^r^

" before R"^Int.toString(regNum)^"\ n");

raise unFreedReg)

else (regNum,color)::freeReg(r, t)

Fig.5. The freeReg function

fun offsetRegs([],offset) = []

| offsetRegs((regNum,color): :t,o ffse t) =

if color <> ~1

then (regNum,color+offset)::(o ffse tRe gs(t ,off set) )

else (regNum,~1)::(offsetRegs( t,of fse t))

fun concatRegs(g1, g2) = offsetRegs(g1,unFreedCou nt g2)@g2

(8)

freeRegingure 5is calledatthe end of thelifetimeof asymbolicregister.

It isgiven asymbolicregisterand aregisterinterference graphand returns

anew registerinterference graphwith the given symbolicregister freed.

concatRegs ingure 6 is called if two registerinterference graphs are to be

merged. This maybe needed ifcode generation has beenperformedontwo

parts of a computation (in a bottom-up fashion) and at some later point

duringcode generation the code ismerged intoone larger computation.

The createReg function uses the -1 (note that in ML -1 is written ~1) to

indicatethat the graphisnot yet completebecause registerswithcolor -1are

still alive. The freeReg function uses a result from the theorem. All registers

that followa given register, r, in the register list and are not yet freed must

be neighbors of r. Assume there are k such neighbors. Then, if they are

neighbors, by the lifetime property they must form a k-clique. But it was

proved thatthis issuÆcienttosaythat withthe additionof rthey mustform

a (k+1)-clique. Therefore r should be colored with color k+1. Since colors

begin with 0,the unFreedCount returnsthe next availablecolor.

The freeReg function checks that when a register, r, is freed there are

no other registers created after r that are still alive. If there are other live

registersthatwerecreatedafterr,freeingrwouldviolatethelifetimeproperty

andthereforeisnot allowed. Ineect, thisplacesarstin/rstoutrestriction

onregisterallocationwhichisanotherwayofthinkingofthelifetimeproperty.

Section 6uses the rst in/rst out property inits implementation.

The concatRegs function can be called to combine register interference

graphs at anytime in the future. This is especially useful if your compiler

can'tguaranteealefttorightbottom-uptraversalof theabstract syntaxtree.

Consideringthe computationalcomplexity of the functions abovethe

cre-ateReg function is O(1). The freeReg function must traverse the register list

once for each register that is freed. This is done by calling the unFreedCount

function, whichis then O(jVj)where V isthe set of symbolicregistersin the

register interference graph. The concatRegs function has similar complexity

asit alsocalls the unFreedCount function. Therefore, the framework performs

at least as well as O(jVj 2

). Since calls to freeReg occur interspersed with

the compilation of the code, inpractice there is nonoticable wait forregister

allocationtooccur duringcompilation.

6 An Example Use of the Framework

The framework presented inthispaperhas been successfullyused inpractice.

Inparticular,theActionSemantics-basedcompilergeneratorcalledGenesis[5]

uses an extension of this framework when targeting the MIPS architecture.

The program in gure 1 was compiled by a Genesis generated compiler and

the resulting MIPS code (slightly abbreviated due to length) is presented in

(9)

compilergenerationasitappliestosort inferenceandaction transformations.

Noattempthas beenmadetomakeGenesis'compilersproduceeÆcient code.

Parser

Generator

Generator

Scanner

Grammar

Semantic Specification

Action Semantic Definition (ASD)

ML−lex

ML−yacc

Assembly

Tokens

Action

Program

Annotated Action

Postfix

Action

Machine

Key:

Language Specific

MIPS Assembler

Code Generator

Common

Parser

Scanner

Sort Checker

Lexical Specification

Transformer

Language

Fig. 7. TheGenesis compilergenerator

ThestructureofGenesisisshowningure7. BecauseGenesisisanAction

Semantics-basedcompilergenerator,the programingure1isrsttranslated

to itsaction. Then the actionis sort checked (i.e. typechecking isperformed

onit)toverifythattheactioniswell-formed. Finally,theactionistransformed

beforeit isgiven as inputto the code generator.

Code generation is generally postx in nature. Operands are evaluated

before the operation is applied to the operands. When compiling actions it

makessensetogettheactioninaformasclosetotheformofthelow-levelcode

as possible. That is the responsibility of the action transformer in Genesis'

compilers. It insures that actions are postx in nature. Postx actions give

their operands and then operate onthem. For instance, the action

give2

and then

give3

then

give the sumof the given data

beginsbyevaluatingthetwooperands,bygiving2and3,andendsbyapplying

the sumoperationtothem. A stack machinetargetarchitectureiswellsuited

for postx evaluation. It would be convenient if a register machine could

emulate a stack machine, since stack architectures are easy to target when

(10)

val regStack = ref ([]:string list);

exception emptyRegStack;

fun pushReg r =

(regStack := (r::(!regStack)))

fun popReg() =

(if (!regStack = []) then raise emptyRegStack else ();

let val x as (r::rl) = !regStack

in

regStack:=rl;

r

end)

Fig.8. The pushRegand popReg functions

val regList = ref ([]:(int*int) list);

fun getReg() =

let val result as (r,rl) = createReg(!regList)

in

regList:=rl;

r

end

fun delReg(r) =

let val rl = freeReg(r,!regList)

in

regList:=rl;

()

end

Fig. 9. ThegetReg and delRegfunctions

The register framework presented in section 5 can be used to emuluate a

stack machine during code generation. Withthe additionof afew functions,

symbolicregisterscan be\pushed" and \popped" froma registerstack using

pushReg and popReg. These functions are presented in gure 8. In addition,

a couple of functions simplify calls for creating and freeing registers in the

framework. The functionsgetReg and delReg, ingure 9, imperativelycreate

and free registers usingthe createReg and freeRegfunctions.

TheregisterframeworkpresentedinthispaperisusedforgeneratingMIPS

code in Genesis' compilers. For instance, when the action give 2 is

encoun-tered, the code generator responds by calling the getReg function to allocate

(11)

pushingthe registerontothe registerstack usingpushReg. The actualcodein

the code generator, writtenin ML, looks like this

fun gen_action (give'(y, _)) env =

generate_yielder y env

and generate_yielder (intVal'(i,_)) env =

let val r = getReg()

in

TextIO.output(streamOf env,"\tli "^r^","^Int.toString(i)^"\n");

pushReg(r)

end

When givethe sumofthe givendata isencountered inthe action, thecode

generator knows that addition is a binary operation. The code generator's

code looks like this

fun generate_yielder (sum'(y,_)) env =

let val reg2 = popReg()

val reg1 = popReg()

in

delReg(reg2);

pushReg(reg1);

TextIO.output(streamOf env,"\tadd "^reg1^","^reg1^","^reg2^"\n")

end

There shouldbe two operands onthe simulated registerstack. Upon

rec-ognizingthe additionoperation,the code generator responds by popping two

registers fromthe registerstack, generating code toperform the required

ad-dition, and then pushing the register containing the result onto the register

stack. Notice the registerthat is nolonger needed is freed by callingdelReg.

7 Comparison to Other Work

Chaitin's work on register allocation [2] concentrates on allocating variables

toregisters. Thefocusofthatwork isstudyingthe livenessrangeofvariables.

More recent work by Hendren, et al [4] has extended that work by looking

at interval graphs and hierarchical cyclical interval graphs. In each of these

approaches nodes in the register interference graph correspond to variables

in the programand edges exist between nodes whosecorresponding variables

interfere with each other. Since variables can exist in virtually any order in

a program, there is nostructure tothe correspondinggraphs. The best

algo-rithms for coloringthese graphswill always be based onheuristics, assuming

that NP-complete is reallyNP and not P!

However, one possible advantage of these other approaches is that they

consider register allocation on a procedure or function level. The approach

presented here does not allocate variables to registers. Instead, it focuses on

a simplerproblemofallocatingtransient values(whichmay becopies of

vari-ables) to registers. The idea of allocatingregisters for transient values comes

(12)

an action. By limiting ourselves to values, the resulting register interference

graphs have a structure that can be exploited to minimally color them in

polynomialtime.

Putanotherway,whileotherworkinregisterallocationconcentrateson

al-locatingregistersforanentire procedureorfunction,theframeworkpresented

hereconcentratesonallocatingregistersatthestatementlevel,although

noth-ing ispreventing itfrom being used ona procedure orfunction level.

In comparing the two approaches several things can be said about each

approach. The primary advantage of Chaitin's and Hendren's work is in

re-ducing the number of memory accesses that are needed to place values in

registers. If a variable is assigned to a register for an entire function or

pro-cedure this certainly reduces the number of required loads. Without further

work, the approach presented here will certainly result in more load

instruc-tions. However, withthe adventof largedatacaches inRISCprocessors,load

instructions don't carry nearly the penalty of earlierCISC architectures.

Write operationsmay carry alarger penalty in a RISC architecture since

writes have the potential to invalidate data in the cache. When

consider-ing register allocationon a procedureor function level, spillcode willalmost

inevitablybegenerated, resultinginwritestomemory. However, withthe

ap-proachpresented inthis paper, registerspillingwillhappen very infrequently.

8 Conclusion

Registerallocationcanbeexpressed intermsofsymbolicregistersandregister

interference graphs. If a simple demand policy is employed, register

interfer-ence graphs adhere to the lifetimeproperty. This paperhas shown that such

graphs can be minimally coloredin polynomialtime.

In addition to the somewhat rigorous proof that was given in the paper,

the proof was veried by providing it to an automated inductive theorem

prover. Thetheorem proverconcludedthat graphsthatadheretothe lifetime

property can be minimally colored. The proof demonstrated the coloring

occurs inpolynomial time.

The framework presented inthis papertakesadvantage of the proof. The

graphsitproducesadheretothe lifetimeproperty,essentiallyenforcingarst

in/rst out allocation of registersof the machine.

Futureworkonthisframeworkincludesstudyinghowcodegeneratedwith

it performs when compared to other more conventional register allocation

techniques. If it is found that code generated using this framework performs

signicantly poorer due to an increased number of load instructions, register

loads mightbesuppressed by registercoalescing. Ifregisters canbecoalesced

insuchawaythatthelifetimepropertyispreserved,someregisterloadsmight

beeliminatedwhile stillbeing able tominimallycolor the resultinggraphsin

polynomialtime.

(13)

be studied in the context of preserving the lifetime property. By using this

framework as a basis for further research, researchers can either nd graph

transformations that preserve the lifetimeproperty or understand the

trade-os they are making when abandoning this property in register interference

graphs.

Acknowledgement

I would liketo thank Hantao Zhang for hishelp in gettingthe RRL theorem

prover to prove the theorem presented in this paper. Automated inductive

theorem proving is still something of an art and Hantao was responsible for

(14)

References

[1]A. Bondorf and J. Palsberg. Compiling actions by partial evaluation.

In Proceedings of Conference on Functional Programming Languages and

Computer Architecture (FCPA '93), Copenhagen,DK,1993.

[2]Chaitin, Auslander, Chandra, Cocke, Hopkins, and Markstein. Register

allocationvia coloring. Computer Languages, Vol. 6:47{57,1981.

[3]Garey and Johnson. A Guide to the Theory of NP-Completeness. Freeman,

1979.

[4]LaurieJ.Hendren,GuangR.Gao,ErikR.Altman,and ChandrikaMukerji. A

register allocation framework based on hierarchical cyclic interval graphs. In

Computational Complexity, pages176{191, 1992.

[5]K.D. Lee. Action Semantics-based Compiler Generation. PhD thesis,

Department of ComputerScience, Universityof Iowa, 1999.

[6]K.D. Lee. Postx transformations for action notation. In Proceedings of

AS2000. BRICSNotes SeriesNS-00-6, 2000.

[7]K.D. Leeand H.Zhang. Formal development of a minimal register allocation

algorithm. Technical Report 99-07, University of Iowa, Department of

ComputerScience, Iowa City,IA,1999.

[8]P.D. Mosses. Action Semantics: Cambridge Tracts in Theoretical Computer

Science 26. CambridgeUniversityPress, 1992.

[9]H. Moura. Action Notation Transformations. PhD thesis, Department of

ComputerScience, Universityof Glasgow, 1993.

[10]T. Pittman and J. Peters. The Art of Compiler Design. Prentice Hall,

(15)

bind\output"tonativeabstractionofanaction

before

bind\input"tonativeabstractionofanaction

hence

furthermore

recursively

bind\f"toclosureoftheabstractionof

furthermore

bind\x"tothegiven(integerjtruth-value)

thence

give(integerjtruth-value)boundto\x"

or

give[(integerjtruth-value)]cellboundto\x"

andthen

give5

then

givethesumofthegivendata

before

allocate[datum]cell

andthen

give0

then

storethegiven(integerjtruth-value)#2inthegiven[datum]cell#1

andthen

givethegiven[datum]cell#1

then

bind\i"tothegiven((integerjtruth-value)j[(integerjtru th -value)]cell)

hence

give(integerjtruth-value)boundto\i"

or

give[(integerjtruth-value)]cellboundto\i"

andthen

complete

then

enactapplicationoftheabstractionofanactionboundto\input"tothegivendata

then

storethegiven(integerjtruth-value)#2inthegiven[datum]cell#1

then give1 andthen give2 andthen give3 then

givethesumofthegivendata

andthen

give(integerjtruth-value)boundto\i"

or

give[(integerjtruth-value)]cellboundto\i"

then

givethe(integerjtruth-value)storedinthegiven[datum]cell

then

enactapplicationoftheabstractionofanactionboundto\f"tothegivendata

then

givethesumofthegivendata

then

givethesumofthegivendata

then

enactapplicationoftheabstractionofanactionboundto\output"tothegivendata

(16)

bind\f101"totheabstraction (integer),!(integer)0 of give[integer]cell (0;1) andthen

givethegiveninteger

then

storethegiveninteger#2inthegiven[integer]cell

(0;1) #1 then give[integer]cell (0;1) then

givetheintegerstoredinthegiven[integer]cell

(0;1)

andthen

give5

then

givethesumofthegivendata

andthen give[integer]cell (0;0) andthen give0 then

storethegiven0#2inthegiven[integer]cell

(0;0) #1 andthen give[integer]cell (0;0) andthen

enact\input"atdepth0

(),!(integer)

then

storethegiveninteger#2inthegiven[integer]cell

(0;0) #1 then give1 andthen give2 andthen give3 then

givethesumofthegivendata

andthen

give[integer]cell

(0;0)

then

givetheintegerstoredinthegiven[integer]cell

(0;0) then enact\f 101 "atdepth0 (integer),!(integer) then

givethesumofthegivendata

then

givethesumofthegivendata

then

enact\output"atdepth0

(integer),!()

(17)

.data prmpt: .asciiz"? " .text main: addi$sp,$sp,-40 sw$ra,4($sp) j f101 f101: addi$sp,$sp,-40

sw$ra,4($sp) #storethereturnaddress

sw$t0,0($sp) #storetheaccesslink

sw$s0,8($sp) #preservedacrossfunctioncalls

...

sw$a0,36($sp)

moveR0,$sp #accessingthecellinthiswaysowecanfollowaccesslinksifnecessary

addiR0,R0,36 #nowloadtheaddressofthecell

lwR0,0(R0)

liR1,5

addR0,R0,R1

move$v0,R0

lw$s0,8($sp) #restorepreservedregister

...

addi$sp,$sp,40

jr$ra #andreturn

f101: moveR2,$sp #accessingthecellinthiswaysowecanfollowaccesslinksifnecessary

addiR2,R2,36 #nowloadtheaddressofthecell

liR3,0

swR3,0(R2)

moveR4,$sp #accessingthecellinthiswaysowecanfollowaccesslinksifnecessary

addiR4,R4,36 #nowloadtheaddressofthecell

jal read moveR5,$v0 swR5,0(R4) liR6,1 liR7,2 liR8,3 addR7,R7,R8

moveR9,$sp #accessingthecellinthiswaysowecanfollowaccesslinksifnecessary

addiR9,R9,36 #nowloadtheaddressofthecell

lwR9,0(R9)

move$a0,R9 #puttheparameterintheparmregister

move$t0,$sp #settheaccesslink

jalf101 #callthefunction

moveR9,$v0 #savethefunctionresult

addR7,R7,R9

addR6,R6,R7

move$a0,R6

jal write

lw$ra,4($sp) #restorethereturnaddress

addi$sp,$sp,40 jr$ra write: li$v0,1 syscall jr$ra read: li$v0,4 la$a0,prmpt syscall li$v0,5 syscall jr$ra

equR0$s0 equR1$s1 equR2$s0 equR3$s1 equR4$s0

equR5$s1 equR6$s0 equR7$s1 equR8$s2 equR9$s2

References

Related documents

In this paper, we presented a structured framework in order to demonstrate that how deception can be used and applied to defenses of an application server environment in order

This paper is an exploratory study with its focus on generating a holistic framework of attributes of a product or a service that can be used as a starting point for any new

In this paper we presented a collaborative project planning framework using semantic web technology. The framework consists of six layers including: peer-to-peer layer for

In this paper, a system framework for cooperative positioning of multiple AUV has been presented which includes cooperative localization using swarm robotics,

This paper proposed an algorithm for generating probabilistic matching of location data to paths in transportation network. It presented a theoretical framework for calculating

This paper proposes a design implementation of shift register using non overlapped pulsed latches, to achieve low power and area optimization.. Latches cannot be used in

In the paper a complete framework for quaternion clustering was presented, which consists of a clustering algorithm along with test data generation framework, quaternion

In this paper, we draw on existing sociolin- guistic theory to adapt a technique called register analysis to (a) characterize the linguistic register used by humans in a