• No se han encontrado resultados

VI. Proyecto de inversión para la construcción de un centro de acopio

6.5 Análisis y Evaluación Financiera

Our first approach to generating a code generator from a machine description is known as the Graham-Glanville method after its originators. It represents machine operations by rules similar to those in a context-free grammar, along with cor­ responding machine instruction templates. When a rule matches a substring of a Polish-prefix intermediate-code string (which represents a preorder traversal of a se­ quence of trees) and its associated semantic constraints are met, the part matched is replaced by an instantiation of the left-hand symbol of the rule and a corresponding instantiation of the instruction template is emitted.

A Graham-Glanville code generator consists of three components, namely, intermediate-language transformations, the pattern matcher, and instruction gen­ eration. The first transforms, as necessary, the output of a compiler front end into a form suitable for pattern matching; for example, source-language operators not representable by machine operations might be transformed into subroutine calls, and calls are transformed into sequences of explicit state-changing instructions. The second component actually does the pattern matching, determining what sequence of reductions is appropriate to consume an input string of intermediate code. The third, which is meshed with the second in its execution, actually generates an appro­ priate sequence of instructions and performs register allocation. In the remainder of this section, we concentrate on the pattern-matching phase and, to a lesser degree, on instruction generation.

As an example, consider the subset of lir instructions in Figure 6.1(a), where each argument position is qualified with a number that is used to match intermediate- code substrings with code-generation rules and instruction templates. The corre­ sponding rules and sparc instruction templates are shown in Figure 6.1(b) and (c). In the figure, “ r.w ” denotes a register, “ k.w” a constant, and “ e ” the empty string. The numbers are used both to coordinate matching with code emission and to ex­ press syntactic restrictions in the rules—for example, if the first and second operands in a string must be the same register for the match to succeed, then they would both have the same number.

We use “ T” to denote a load, to denote a store, and mov to denote a register- to-register move in the Polish-prefix code.

As an example, suppose we have the lir code shown in Figure 6.2. Then, assuming r3 and r4 are dead at the end of this code sequence, there is no need to include them explicitly in the tree representation, as shown in Figure 6.3, but we do need to retain r l and r2. The resulting Polish-prefix form is

140 Producing Code Generators Autom atically r .2 <- r.1 r .2 r . l or r . 1 ,0 ,r.2 r .2 <- k .l r .2 => k .l or 0 ,k .1, r .2 r .2 <- r . l r . 2 ==> mov r . 2 r . l or r . 1 ,0 ,r.2 r .3 <- r . l + r .2 r .3 => + r . l r .2 add r . l , r . 2 , r . 3 r . 3 <- r . l + k.2 r .3 => + r . l k.2 add r . l , k . 2 , r . 3 r .3 <- k .2 + r . l r .3 => + k.2 r . l add r . l , k . 2 , r . 3 r .3 <- r . l - r .2 r .3 => - r . l r .2 sub r . l , r . 2 , r . 3 r .3 <- r . l - k.2 r .3 => - r . l k.2 sub r . l , k . 2 , r . 3 r . 3 <- [r.l+ r.2 ] r .3 => t + r . l r .2 Id [ r . l , r . 2 ] , r .3 r .3 <- [r.l+ k .2 ] r .3 => t + r . l k.2 Id [ r . l , k . 2 ] , r .3 r . 2 <- [ r .l] € ==> t r .2 r . l Id [ r . l ] , r . 2 [r ,2 + r ..3] r . l € => <- + r .2 r .3 r . l S t r.l,[r.2,r.3] [r.2+k..1] <- r.l € = > < - + r.2 k.l r.l S t r.l, [r.2,k.l] [r2] <--r.l € => <- r.2 r.l S t r.l,[r.2] (a) (b) (c)

FIG* 6.1 (a) lir instructions, (b) Graham-Glanville machine-description rules, and (c) corresponding sparc instruction templates.

r2 [r8] r l <- [r8+4] r3 <- r2 + r l [r8+8] <- r3 r4 r l - 1 [r8+4] <- r4

FIG. 6.2 A lir code sequence for Graham-Glanville code generation.

T r2 r8 <- + r8 8 + r2 T rl + r8 4 <- + r8 4 - rl 1

The pattern matching that occurs during its parsing is shown in Figure 6.4, along with the sparc instructions generated for it. The underlining indicates the portion of the string that is matched, and the symbol underneath it shows what replaces the matched substring; for loads and arithmetic operators, the resulting register is determined by the register allocator used during code generation.

6.2.1

The Code Generator

The code generator is essentially an SL R (l) parser that performs the usual shift and reduce actions, but that emits machine instructions instead of parse trees or intermediate code. In essence, the parser recognizes a language whose productions are the machine-description rules with “ e ” replaced by a nonterminal N and the additional production S => N *. There are, however, a few important differences from SLR parsing.

Section 6.2 A Syntax-Directed Technique 141 t <7- add add r2 r8 r8 8 r2 T add sub rl add r8 rl r8 4

FIG. 6.3 Trees corresponding to the lir code sequence in Figure 6.2.

<- + r8 8 + r2 T rl + r8 4 <- + r8 4 - rl 1 rl <- + r8 8 + r2 rl <- + r8 4 - rl 1 r3 <r- + r8 4 r3 <- + r8 4 - rl 1 e <r- + r8 4 - rl 1 r4 <r- + r8 4 r4 (a) 1 - rl Id 1 [r8,0],r2 Id [r8,4],rl add r2,rl,r3 St r3, [r8,4] sub rl,1,r4 St

(b)

r4,[r8,4]

FIG. 6*4 (a) Parsing process and (b) emitted instructions for the trees in Figure 6.3.

Rules with “ e ” on the left-hand side are allowed, and the “ e ” is treated as a nonterminal symbol. Unlike in parsing, machine-description grammars are almost always ambiguous. The ambiguities are resolved in two ways. One is by favoring shift actions over reduce actions (i.e., the algorithm is greedy or maximal munch) and longer reductions over shorter ones, so as to match the longest possible string. The other is by ordering the rules when the parsing tables are produced so that the code generator picks the first rule that matches when it performs a reduction during code generation. Thus, in specifying the rules, one can bias code generation to particular choices by ordering the rules in a particular way or by building a cost evaluation into the code generator.

142 Producing Code G enerators Autom atically

The code-generation algorithm uses seven global data types, a stack, and two functions that are constructed by the code-generator generator, as follows:

Vocab = Terminal u Nonterminal ExtVocab = Vocab u {•e 1,'$1} VocabSeq = sequence of Vocab

ActionType = enum {Shift,Reduce,Accept,Error} I I type of machine grammar rules

Rule = record {It: Nonterminal u {'e'}, r t : VocabSeq}

I I type of parsing automaton items that make up its states