Вы находитесь на странице: 1из 14

Engineering a Simple, Efficient Code-Generator Generator

CHRISTOPHER AT& TBell W, FRASER Laboratories

DAVID R. HANSON Princeton and TODD A. PROEBSTING The University of Arizona University

Many code-generator generators use tree pattern matching and dynamic programming. This paper describes a simple program that generates matchers that are fast, compact, and easy to understand. It is simpler than common alternatives: 200700 lines of Icon or 950 lines of C versus 3000 lines of C for Twig and 5000 for burg. Its matchers run up to 25 times faster than Twigs, They are necessarily slower than burgs BURS (bottom-up rewrite system) matchers, but they are more flexible and still practical. Categories
ation;

and Subject Descriptors:


translator writing

D.3.4 [Programming
systems and compiler

Languages]:
generators

Processorscode

gener-

compilers;

General

Terms: Languages Key Words and Phrases: Code generation, code-generator Icon programming language, tree pattern matching generator, dynamic pro-

Additional gramming,

1. INTRODUCTION
Many code-generator generators programming (DP) [2, 4, 8]. They and semantic actions produce that, tree for code. They with with matchers use tree pattern matching and dynamic accept tree patterns and associated costs, allocate make two registers passes and over that emit each object subject that

example,

tree. The first minimum

pass is bottom patterns on this

up and finds at the

a set of patterns the semantic they matched. [7], Twig

cover the tree associated [ 13]. Code-generator

cost. The second pass executes nodes BEG model include

actions

minimum-cost based

generators

[3], and burg

Authors addresses: C. W. Fraser, AT&T Bell Laboratories, 600 Mountain Avenue 2C-464, Murray Hill, NJ 07974-0636; D. R. Hanson, Department of Computer Science, Princeton University, Princeton, NJ 08544; T. A. Proebsting, Department of Computer Science, The University of Arizona, Tucson, AZ 85721. Permission to copy without fee all or part of this material is granted provided that the copies are not made or distributed for direct commercial advantage, the ACM copyright notice and the title of the publication and its date appear, and notice is given that copying is by permission of the Association for Computing Machinery. To copy otherwise, or to republish, requires a fee and/or specific permission. @ 1992 ACM 1057-4514/92/0900-0213 $01.50 ACM Letters on Programming Languages and Systems, Vol. 1, No. 3, September 1992, Pages 213-226,

214

C.

W. Fraser et al.
are hard-coded parsers time to identify and mirror the their tree input cover. of string matching [ 1, 15] that, in is but patterns grammars. in the They same use

BEG way that

matchers

recursive-descent

mirror variant

DP at compile Twig matchers

a minimum-cost

use a table-driven

essence, identifies all asymptotically better overhead is higher.

possible matches at the same time. This algorithm than trying each possible match one at a time, BEG matchers, cover. rewrite Twig system) matchers theory use DP [5,6,

Like

at compile

time to identify a minimum-cost burg uses BURS (bottom-up

17, 18] to move

the DP to compile-compile time. BURS but BURS matchers generate optimal main disadvantage of BURS is that delay DP until compile This paper describes tion and writes hard-coded, generators a technique [9, 12]. iburg

table generation code in constant costs must

is more complicated, time per node. The systems that

be constants;

time permit costs to involve a program called iburg that that that has does DP at compile effective proved

arbitrary computations. reads a burg specificatime. The matcher evolved is into with other of what types of code

a matcher

was built

to test early

versions

burgs specification language and interface, but it is useful in its own right because it is simpler and thus easier for novices to understand, because it allows dynamic cost computation, grammars [16]. iburg has been and because it admits used with good results a larger class of tree in a first course on

compilers. burg and iburg have MIPS, and SPARC code generators

been used also to produce robust VAX, for lCC, a retargetable compiler for ANSI matchers, reference programs but this paper describes them in the

[11]. iburg

and BEG than optimizations

produce the that

similar paid

more several

detail

standard

BEG

[7]. In particular, did not, when compared with

it describes programs

off and two that

and it quantifies

strengths like Twig

and weaknesses and burg.

of such

2. SPECIFICATIONS
Figure tions. 1 shows Grammar an extended symbols BNF grammar in for italic burg type, and and iburg terminal specificasymbols of X, a %% in are displayed

are displayed in typewriter and [X] denotes an optional separator, and rules. The

type. {X} denotes X. Specifications declarations declare

zero or more instances consist of declarations, terminalsthe

operators

subject treesand associate a unique, positive external symbol number with each one. Nonterminals are declared by their presence on the left side of rules. The %start declaration optionally declares a nonterminal as the start symbol. In Figure 1 term and nonterm denote identifiers that are terminals and nonterminals, respectively. Rules define tree patterns in a fully parenthesized prefix form. Every nonterminal denotes a tree. Each operator has a fixed arity, which is inferred rule is a rule whose pattern is from the rules in which it is used. A chain another nonterminal. If no start symbol is declared, the nonterminal defined by the first rule is used.
Languages and Systems, Vol. 1, No. 3, September 1992.

ACM Letters on Programming

A Simple, Ellicient Code-Generator

Generator

215

grammar
dcl

+
-+

{dcl}~~ %start

{rule) nonterm integer}


[ cost ] ;

I
rule cost tree + + + I \

%terrn { identifier=
nonterm ( integer term term : tree ) , tree )

= integer

( tree ( tree)

term nonterm for burg and iburg specifications.

\ Fig. 1. Extended

BNF grammar

1.

%term %term TL stint: stint: reg: reg: reg: reg: disp: disp: rc: rc: con: con:

ADDI=309 CNSTI=21

ADDRLP=295 ASGNI=53 CVCI=85 101=661 = 4 (i); = 6 (l); = 7 (l); INDIRC=67

2. 3. 4, 5. 6. 7. 8. 9.
10. 11. 12. 13. 14. 15.

ASGNI(disp,reg) reg = 5; ADDI(reg,rc) 101 = 8; disp = 9 (l); ADDI(reg,con) ADDRLP = 11; con = 12; reg = 13; CNSTI = 14; 101 = 15: Fig.2. Sample burg

CVCI(INDIRC(disp))

= 10;

specification.

Each

rule

has aunique,

positive

external

rule

number,

which

comes

after

the pattern andis preceded by an equal sign.As described below, rule numbers are used to report the matching ruleto auser-supplied tic action routine. Rules end omitted costs defaultto zero. Figure example 1-2 2 shows a fragment uses uppercase the operators with an optional nonnegative, for the

external semancost; This Lines 4-15

integer VAX.

of a burg external

specification symbol

for terminals and their

and lowercase

for nonterminals. numbers, and lines

declare

give the rules. The external rule simplify interpreting subsequent

numbers figures.

correspond to the line numbers to In practice, these numbers are

usually generated by a preprocessor (e.g., including YACC-style semantic tion [13]. Only the rules on lines on lines 5, 9, 12, and 13 are chain

that accepts a richer form of specification actions) and that emits a burg specificanonzero costs. The rules rules.
Languages and Systems, Vol. 1, No. 3, September 1992.

4, 6, 7, and 9 have

ACM Letters on Programming

216 The operator

C. W. Fraser et al, in Figure The with operator and pointer integer integer 2 are some names of the operators like in lCCS intermediate a generic denote used in of a local constant

operators [10]. name 2 denote

language character, Figure variable

are type (ADDI),

formed suffix

by concatenating The operators the an address integer

a one-character addition

C, I, or P, which

integer, (ADDRLP),

operations, assignment

respectively. forming (ASGNI),

(CNSTI), widening a character to an integer (CVCI), and fetching a character (INDIRC). The rules show that are binary; CVCI and INDIRC are unary; and ADDRLP, are leaves. 3. MATCHING Both reduce tree versions subject the of burg trees. minimum pass over generate The the labeling subject cost, functions function, tree is such that the label(p), the a cover. client

the integer O (101), ADDI and ASGNI CNSTI, and 101

calls rules

to label that cover rule

and the M

makes Each with

a bottom-up, node is labeled

left-to-right with

p computing associated tree

if there

with (M, C) to indicate that the matches the node with cost C. Figure 3 shows the intermediate C fragment: +4;} node which Figure sion in the following {inti; The left computes charc; child i=c

pattern language

external

for the

assignment

expres-

of the ASGNI

computes

the

address widens

of i. The right it to an integer,

child and C)

the address

of C, fetches

the character,

adds 4 to the widened value, The other annotations in

the ASGNI assigns to i. 3 shows the results of labeling.

(M,

denote labels from matches, and [M, C] denote labels from chain rules. The rule from Figure 2 denoted by each M is also shown. Each C sums the costs of the pattern nonterminals or chain rule. on the i with right-hand side and the cost with(11, of the relevant 2 matches For example, the pattern in line 11 of Figure

the node ADDRLP

cost O, so the node is labeled

O). Since this

pattern denotes a disp, the chain rule in line 9 applies with a cost of O for matching a disp plus 1 for the chain rule itself. Likewise, the chain rules in lines 5 and 13 apply can specify in line because subtrees the chain beyond 2 refers rule in line 9 denotes children. a reg. For example, node. No Patterns the pattern the immediate to the grandchild

7 of Figure

of the CVCI

separate pattern matches the INDIRC node, but node. The cost is the cost of matching the ADDRLP 11, plus 1. Nodes are annotated with (M, C) only if C

line 7s pattern covers that i as a disp, which is rule is less than all previous

matches for the nonterminal on the left-hand side of rule M. For example, the ADDI node matches the disp pattern in line 10 of Figure 2, which means that it also matches all rules with disp alone on the right-hand side, namely, line 9. By transitivity, it also matches the chain rules in lines 5 and 13. But all three of these chain rules yield cost 2, which is not better than previous matches for those nonterminals. Once labeled, a subject tree is reduced by traversing it from the top down
ACM Letters on Programming Languages and Systems, Vol. 1, No 3, September 1992.

A Simple, Efficient Code-Generator

Generator

217

disp:

ADDRLP (11, o) disp reg


reg

(4, 0+2+1=3)

stint: ASGNI (disp,


(6, 1W+1=2)

reg)

resf:

stint: rc:

[9, 0+1=1] [5, I*II


[13, 1*1]

ASGNI

re9: ADDI (reir, rc) stint: zeg


rc: reg

(10, ItO+O=l) disp:

ADDI(re9,

con)

reg:

C!VCI(INDIRC(disP) ) stint: reg


rc: reg

(7, 0+1=1)

[5, 1*1] [13, lW=l] INDIRC

con: CNSTI (14, o) [12, 0+0=0] rc: cm

A
and that by performing in these identifies appropriate traversals, subtrees emitting another burg code. Reducers that are supplied assist

(11, o) [9, 0+1=1]


[5, lM=ll [13, 1+0=1]

disp : ADDRLP reg: disp


stint: m: rw reg

ADDRLP C

Fig. 3. Intermediate language tree for i = c + 4.

semantic for example, for recursive time

actions,

such

as generating generates that returns

and M and a

by clients,

but burg

functions

one function visits. and annotates

Reference

[13] elaborates. each node with concernannotates pointers accesses

does all DP at compile-compile

single, integral state number, ing matches and costs. iburg nodes with data equivalent

which encodes all of the information does the DP at compile time and C). Its state numbers are really that

to (M,

to records that hold these data. Both versions of burg generate

an implementation or functions

of label

node fields via client-supplied macros function state to identify matches: int

and uses the nonrecursive

label(NODEPTR_TYPE p) { if (p) { int 1 = label(LEFT_CHILD(p)); int r = label(RIGHT.CHILD(p)); return STATE_LABEL(p) = state(OP_LABEL(p), } else return O;

1, r);

} NODEPTR.TYPE nodes. OP_LABEL, functions child, state that return, field. and its right number is a typedef or macro that defines the data type LEFT. CHILD, and RIGHT_ CHILD are macros respectively, child. a nodes external is a macro symbol that number, accesses STATE_LABEL of or

its left a nodes

state accepts an external symbol number for a node and the state numbers for the nodes left and right children. It returns the state number to assign to that node. For unary operators and leaves, it ignores the last one or two arguments, respectively.
ACM Letters on Programming Langnages and Systems, Vol. 1, No. 3, September 1992.

218

C. W. Fraser et al

4. IMPLEMENTATION
iburg of tree state Figure generates pattern numbers for a state matching successful function [7]. It that uses a straightforward hard code instead hold for the records, state which record implementation of tables. specification Its in vectors of the (M, generates The

are pointers

to state

C) values

matches.

2 is the following: struct state { int op; struct state * left, short cost[6]; short rule[6]; };

* right;

iburg cost

also

generates vectors:

integer

codes

for

the

nonterminals,

which

index

the

and rule #define #define #define #define #define

stmt_NT 1 disp_NT 2 rc_NT 3 reg_NT 4 con_NT 5 the start a nonzero that defines the nonterminal when value for has the value allocated, X. of state on the and gives symbol the cases that are allocates and initializes to begin test for a by itself is called that switch and p + rule[ 1. rule numbers that ps are node

By convention, State positive. matched Figure contributed a new state records Thus, a rule

are cleared

external

X ] indicates

nonterminal

4 shows record

implementation 2s lines switches

by Figure

6, 7, 10, and 11. state external

and

number

matching. Each nonleaf case is one or more if statements match by consulting the state records of descendants. The does all the necessary If a match with succeeds, to the the pointer testing state for leaves. cost is computed, the rule number: cost, int eruleno) the resulting record, external

and record

code for the matching

nonterminal,

the cost, and the matching

void record(struct state *p, int if (cost < p ~ cost[ntl) { p ~ cost[ntl = cost; p ~ rule[ntl = eruleno; 1

nt, int

The

match

is recorded

only

if its

cost

is less with

than

previous

matches.

The

elements of the cost, so the first

cost vector are initialized match is always recorded.

32767

to represent

infinite

The first call to record is for the match itselfi the other calls are for chain rules. For example, the second if statement in the ADDI case tests whether ps node matches the pattern records that the node matches
ACM Letters on Programming

in line 10. If it does, the first call to record a disp. The chain rule in line 9 says that a

Languages and Systems, Vol. 1, No, 3, September 1992.

A Simple, Efficient Code-Generator

Generator

219

int

state(int int c; struct

op,

int state

left, *1 *r = =

int

right) state state

{ *)left, *)right, *p;

(struct (struct

p = malloc(sizeof p->op p->rule[l] switch case if (op) ADDI: (1->rule[reg-lJTl = op; = { p->left

*p); = 1; p->right = = r; . . . = 32767;

. . . = O;

p->cost[l]

r->rule[rc_NT)

c = l->cost[reg_NT]

+ r->cost[rc_NT]
C, 6) ; 13); 5); c + O,

+ 1;

record(p,
record(p, record(p, } if (1->rule[reg-IiT]

reg_NT,
rc_NT, stmt_NT,

c + O,

kk disp_NT, reg_NT, rc_NT, stmt_NT,

r->rule[con_NTl) + r>cost[con_NT] c, 10); 9); 13); 5);

{ + O;

c = l>cost[reg_NT] record(p, record(p, record(p, record(p,

c + 1,

c + 1 + O, c + i

+ O,

3
break; case ADDRLP: C=o; record(p, record(p, record(p, record(p, break; case if CVCI: (1->op == INDIRC &k l->left->rule[disp-NT]) + 1; { disp_NT, reg_NT, rc_NT, stmt_NT, c, c + 11); 1, 9); 13); 5);

c + 1 + O, c + 1 + 0,

c = l->left>cost record(p, record(p, record(p, 1 break; . . . 3 return } Fig. 4. (int)p; reg_NT, rc_NT, stmt_NT,

[disp_NT] C, 7); 13);

c + 0,

c + 0,

5);

Implementation

of state.

ACM Letters on Programming

Languages and Systems, Vol. 1, No. 3, September 1992.

220

C. W. Fraser et al.
a disp rules also matches in lines and a reg with an additional say that closure cost of 1, which are a a node matching cost rules

node matching due to the reg also chain

gives rise to the second record matches a stint

call. Likewise, 5 and an rc, both

the last two calls to record with an additional

13, which

of O. In

general, there is a call to record for the transitive that reach the nonterminal defined by the match.

of all chain

5. IMPROVEMENTS
The generated code-generation Students a couple that make matcher described and in the previous the generator emits however, smaller 642 lines vector that section itself several and faster. is practical for many 4 in imrule exam-

applications, iburg iburg

is easy to implement. in Figure with the simple Even improvements

have replicated of weeks. the below, but many generated

the version implements, matchers takes only

the code shown

provements The short number,

of Icon [14]. any external For by only a few rules.

elements

of the rule

can accommodate

nonterminals

are defined

ple, only lines 10 and 11 in Figure to record one of the two positive compact bit fields, range of integers and as in the following

2 define disp, so only two bits are needed values. Definitions can be mapped into a in minimum space in state records as

stored

example:

struct state { int op; struct state * left, *right; short cost [6]; struct { unsigned int stmt:2; unsigned int disp:2; unsigned int rc:2; unsigned int reg3; unsigned int com.2; } rule; }; External number rule that external short short short short short rule numbers for matches to map the are retrieved iburg integers in the example: by calling compact rule with a state of to

and a goal nonterminal uses tables rule numbers,

[13].

generates

an implementation representation

as in the following [1= = [ 1= [1 = [1 = {O, {o, {O, {O, {O, 10,11 ]; 12, 131; 4,5 }; 6,7,8,9 }; 14,15];

decode_disp decode_rc [ decode_stmt decode_reg decode_ con

int rule(int state, struct state * p switch (goalnt) case disp_NT case rc_NT.
ACM Letters on Programming

int goalnt) { = (struct state * )state; { return decode. disp[p + rule. disp]; return decode_rc[p -+ rule.rc];
Languages and Systems, Vol. 1, No. 3, September 1992

A Simple, Efficient Code-Generator case stmt_NT case reg_NE case con_ NT: } return return return decode_ decode_ decode_ stmt[p ~ rule. stint]; reg[p - rule.reg]; con[p ~ rule. con];

Generator

221

1
Packed

rule

numbers

cannot

be subscripted,

so record

and

the

code that

tests for a match large specifications. and the encoding bytes. Packing and decode much ized With faster, rule packed rule

must be changed. This scheme can save much space for For example, the VAX specification has 47 nonterminals, scheme reduces the size of its rule vector from 96 to 16 can also numbers, structure assignments original packed start fields. further needs still: All costs much The be set, but rule fields symbol initialization. save time: It takes longer VAX yet, to read, matcher been but that write, initialslower. swamps

numbers rule a single 47 the

packed with with

but the smaller a structure would copy be

structure would slower

can be initialized have

copy. The original

47 assignments; fields,

a 16-byte

structure the other only

copy beats

47 assignments

by a margin

costs of using field

Initialization the rule

costs can be reduced for the

are read in only match. The rule always fields tion then will rule begins should at all. the prevent numbers that initializers zero They

two places: the rule function above, and the tests for a function is called during a top-down tree traversal, which the start symbol then fields match. as the the tree goal nonterminal. to match, require if they If it finds and read no rule the rule read number, the failed a false rule failed tests no more initializagarbage, which packing cost in

with

be examined

anyway.

The match

of descendants; and their With this improved

descendants recording no longer

to match,

costs will saves space, in record

be infinite, initializer,

saves time,

but it still

and the time fails, the tests

is so small record

it could

not be measured. If the cost test implement its chain rules must fail too, because These calls can be avoided if the cost test both this improvement and packed rules. in the ADDI case in Figure 4 becomes costs fails. For the

can also be improved.

the calls to record that increase monotonically. Inlining example, following: record the second

accommodates if statement

if (1 -+ rule.reg && r -+ rule. con) { c = 1- cost[reg_NT] + r ~ cost[con_NT] + O; if (c < p -+ cost[disp_NT]) { / * disp: ADDI(reg, con) * / p - cost[disp_NT] = c; p s rule.disp = 1; closure_ disp(p, c); }

1
P ~ ~le.disp rule 10. This each nonterminal

k set to 1 because
a more that

decode_disp approach via

above

maps

1 to external rules. For

code also shows X

compact

to handling chain rules,

chain iburg

can be reached

generates

ACM Letters on Programming

Languages and Systems, Vol. 1, No. 3, September 1992.

222

C.

W. Fraser et al. cost is better than function. For exam-

closure_X, which records the chain rule match if its previous matches and, if applicable, calls another closure ple, the closure function for disp is the following: void closure_ disp(struct state *p, int c) { if (c + 1 < p - cost[reg_NT]) { / * reg disp p ~ cost[reg_NTl = c + 1; p ~ rule.reg = 4; closure_ reg(p, c + 1); } 1 The incoming rule. reg This disp, cost, c, is the cost of matching the cost of the chain cost of this application function. rule is the

*\

the right-hand itself, of the chain handles rule,

side of the chain 1 for line this sum rules chain 9s is for and

cost plus

for example, both

passed to the next closure reg (lines 5 and 13):

closure_reg

void closure_reg(struct state *p, int c) { if (c + O < p ~ cost[rc_NT]) { \ * rc: reg * / p ~ cost[rc_NTl = c + O; p ~ rule.rc = 2; 1 if (c + O < p ~ cost[stmt_NT]) { / * stmti reg * / p - cost[stmt_NT] = c + O; p ~ rule.stmt = 2; } } The final improvement saves times for leaves, which abound in subject

trees from code generators. record data about matches Leaves, however, always

The computation and encoding at compile-compile time are match, and the contents of the

of all of the state complicated [18]. state record are and closure be allocated case in

easily computed by simulating the effect of the assignments function calls shown above. The state records for leaves can thus and initialized at compile-compile Figure 4 becomes the following: case ADDRLP. static struct { state time; for example, the

ADDRLP

z = { 295,0,0,

{ o,
1,/ * stint: O,/ * disp: rcireg 1,/. 1,/ * reg 32767, },{2, / * stint: 2,/ * disp: rc:reg 2,/. 4,/ * reg }};O return } reg * / ADDRLP
./

*/

disp

*/

reg */ ADDRLP
*/

*/

disp

*/

(int) &z;
Languages and Systems, Vol. 1, No. 3, September 1992

ACM Letters on Programming

A Simple, Efficient Code-Generator


Table I. iburg size 566 580 580 616 642 Matcher size 240)140 56,304 56,120 58,760 66,040 ICC time 2.5 2.4 2.4 2.2 2.2 Improvements

Generator

223

Matcher time .69 .59 .59 .39 .39

Version Original untuned version Inline record; add closure routines Initialize only one element of rule Precompute leaf states Pack rule numbers

The

first

three

values

initialize

the

op,

left,

and

right

fields

of the

state

structure. The two brace-enclosed initializers given the cost respectively. The code at the beginning of state (see Figure and initializes test that Table shows tion resulting the state machines Closure one place ment must could I traces the number cost. The matcher. a state the record addition column processor. is not needed of each of Icon column shows for leaves, excludes leaf ops. improvement the number lcc column above. of

and rule values, 4) that allocates by a column in spent the in

so it is protected The first bytes

of lines The third

in iburg times

and helps

quantify object

implementa-

second

in a typical shows

cross-compilation the time for RISC rules improveand have state must in

for the VAX

on a MIPS

The fourth

and rule routines. All times are in seconds. would show smaller improvements. routines rather save so much than in multiple in this other On the the half. space because record trial, hand, small, but they runs. packing The

Specifications implement initialization numbers the chain

not be measured but

it is trivial rule

to implement size of the

save something. by almost

cost some time, structure

cost appears

and it cuts

Two proposed improvements proved uneconomical. First, the closure routines were inlined; measurements showed that the matcher was faster, but it was larger than even the initial version above. Independently, the closure routines were recoded to avoid tail recursion, but no speedup was measured. The recoding replaced ment, and the switch possible that though large Much parsing the respectively, each closure routine bound check added with a case in a switch stateunnecessary overhead; so it is of tail recursion could For do better, example,

a compiler implementation speedups seem unlikely. processing done by iburg input and writing the output in the 642-line final version. written in C is 950 lines,

of the

is straightforward.

account for 181 and 159 lines, By way of comparison, a new and a burg processor is 5100 lines

version of iburg of C [18].

6. DISCUSSION
iburg was built to test early versions of what evolved into burgs specification language and interface. Initial tests used Twig and a Twig preprocessor, but Twig produced incorrect matchers for large CISC grammars. The error proved hard to find, so Twig was abandoned and iburg was written. The

ACM Letters on Programming

Languages and Systems, Vol. 1, No. 3, September 1992.

224

C.

W. Fraser et al.
Table 11, Times for Compiling C Programs the SPEC Benchmarks Benchmark iburg 90.2 iburg 77.9 in

Ool.gcc 008.espresso 022.li 023.eqntott

28.3 8.9 5.6

24.6 8.0 4.9

initial

version

was

completed with full

in two

days

with

200 lines debugging

of Icon.

The

final, is 642

student-proof lines. Matchers

version generated

burg-compatible are slower than

support burg.

by iburg

those

from

Table

II

shows the times for compiling the C programs in the SPEC benchmarks [19] with two versions of lCC. These times are for running only the compiler proper; preprocessing, assembly, and linking time are not included. The compilations were done on an IRIS 4D/220GTX 3.3.2, and the times are elapsed time in seconds times over at several least runs 96 on a lightly utilization times loaded [i.e., achieved percent with 32MB and are the machine. the ratio All running IRIX lowest elapsed reported runs (user +

of times to differences

system) /elapsed The differences performance iburgs matcher rule

> 0.96]. in compilation matchers. identical

are due entirely shows rule. that

in the time iburgs burgs faster. correctly a few lcc of

of the two is nearly

Profiling to burgs

the time,

execution inputs, whereas

On these

accounts

for 8.5 12.4 percent

of the execution

accounts for only 1. 12.0 percent, making burg Comparable figures for Twig are unavailable process large grammars, were but before Using work with measurements taken. a nearly

roughly 6 12 times because it did not Twig complete was abandoned, VAX

grammar,

compiled one 2000-line module using a matcher from the initial

in 20.71 s using iburg; it spent

a Twig matcher and 5.35 s 15.64 s in the Twig matcher

and 0.85 s in the iburg matcher. Using a partial MIPS grammar, ICC compiled the module in 9.19 s using a Twig matcher and 4.54 s using a matcher from the initial iburg; it spent 4.04 s in the Twig matcher and 0.16 s in the slowed slower. iburg, iburg matcher. Both versions which of Icc is why used a naive emitter that was with with by complex grammars, the VAX compiler was so much

The figures in but the naive

this paragraph emitter makes matchers

are useful for comparing Twig them useless for comparisons is that the costs must

anything else. A disadvantage

of BURS

be constant

because the DP is done at compile-compile however, can involve arbitrary computation example, ASGNI(disp, the pattern CNSTI)

time. Costs in Twig specifications, and can depend on context. For

specifies a clear instruction if the constant is O. Twigs cost computations can inspect the subject tree and return a cost of, say, 1 if the constant is O and infinity otherwise.
ACM Letters on Programming Languages and Systems, Vol. 1, No, 3, September 1992,

A Simple, EfFicient Code-Generator BURS tional state, specifications that can handle identify the pass changes this CNSTI kind of context

Generator sensitivity

. with

225 addicalling

operators

special

cases. For

example,

before

lCCS labeling ASGNI(disp,

to 101 if the constant

is O. Thus,

101)

specifies a clear instruction. Most context-sensitive cases that machines, can be handled similarly, example, rules could rml
L(J.

arise in code generation, even for CISC perhaps with a few additional rules. For indexed addressing much like mode BEGs state their parser prefer takes predicates conditions and mirrors label its 12 easily be extended so that

recognizing

and using iburg and tested during that

the VAXs could during

in lCCS specification. be specified

matching, The Indeed, iburg but

iburg functions tion LL(l)

can be useful

development.

generated they mirror

are easy to read This that

and to debug. has made

specificaIt has been

in the same way grammar.

the code for a recursive-descent ideal used Twig, mistakes numbers students

attribute previously

for teaching.

used in a course

iburg.

When like from

students make their inevitable Twigs or burgs, only inscrutable the debugger. When records the matching easily compare

with a table-driven matcher from the table are available

they make mistakes with iburg, each rules and costs for each nonterminal, actual operation with their

node explicitly so users can

the matchers

expectations.

ACKNOWLEDGMENTS

Section The ton.edu

2 borrows in pub.

from

[13],

parts

of which

were

written ftp

by Robert from

Henry.

C version

of iburg

is available

for anonymous

ftp.cs.prince-

AUTHORS

NOTE

Section fields.

5 notes that
BEG

the cost tests this ADDI

make

it unnecessary one step further.

to initialize Tests like

most rule the outer fields are 2. an

[7] carried

observation

if statement embedded This improvement,

in the improved sufl-lce. has terminals but

case in Section

5 need not test rule on line not

at all; the cost tests improvement

Such if statements the INDIRC to iburg. added

are necessary in the rule Trials could

only if there 7 of Figure quantify to read.

to test, like been it probably

saves something,

and it is easier

REFERENCES

1. AHO, A. V., AND COHASICK, M. J. Efficient string matching An aid to bibliographic search. Commun. ACM 18, 6 (June 1975), 333-340. 2. AHO, A. V., AND JOHNSON, S. C. Optimal code generation for expression trees. J. ACM 23, 3 (July 1976), 488-501. 3. AHO, A. V., GANAPATHI, M., AND TJIANG, S. W. K. Code generation using tree matching and ACM Trans. Program. Lang. Syst. 11, 4 (Oct. 1989), 491-516. dynamic programming. Principles, Techniques, and Tools. 4. AHO, A. V., SETHI, R., AND ULLMAN, J. D. Compilers:

Addison-Wesley, Reading, Mass., 1986.


ACM Letters on Programming Languages and Systems, Vol. 1, No. 3, September 1992.

226

C. W. Fraser et al

5. BALACHANDRAN, A., DHAMDHERE, D. M., AND BISWAS, S.


tion using bottom-up tree pattern matching. 6. CHASE, D. R. An improvement to bottom-up

Efficient retargetable code generaJ. Corrqmt. Lang. 15, 3 (1990), 127-140. tree pattern matching. In Conference Record of the ACM Symposium on Principles of Programming Languages (Munich, Germany, Jan. 21-23, 1987). ACM, New York, 168-177. 7. EMMELMANN, H., SCHROER, F.-W., AND LANDWEHR, R. BEGA generator for efficient back of the SIGPLAN 89 Conference on Programming Language Destgn and ends. In Proceedings In
Code

Implementation. SIGPLAN Not. (ACM) 24, 7 (July 1989), 227-237. 8. FERDINAND, C., SEIDL, H., AND WILHELM, R. Tree automata for code selection. GenerationConcepts, Tools. Techniques, Proceedings of the International Workshop

on Code

Generation (Dagstuhl, Germany), R. Giegerich and S. L. Graham, Eds. Springer-Verlag, New York, 1991, 30-50. of the SIGPLAN 89 9. FRASER, C. W. A language for writing code generators. In Proceedings Conference on Programming Language Design and Implementation. SIGPLAN Not.

(ACM)
Pratt. Not.

24, 7 (July 1989), 238-245.


10. FRASER, C. W., AND HANSON, D. R. A code generation interface for ANSI C. Softw. Exper. 21, 9 (Sept. 1991), 963-988. 11. FRASER, C. W., AND HANSON, D. R. A retargetable compiler for ANSI C. SIGPLAN
(ACM) 26,

12. 13. 14. 15. 16.

17.

10 (Oct. 1991), 29-43. FRASER, C. W., AND HENRY, R. R. Hard-coding bottom-up code generation tables to save time and space. Softw. Pratt. Exper. 21, 1 (Jan. 1991), 112. FRASER, C. W., HENRY, R. R., AND PROEBSTING, T. A. BURGFast optimal instruction Not. (ACM) 27, 4 (Apr. 1992), 6876. selection and tree parsing. SIGPLAN GRISWOLD,R. E., AND GRISWOLD, M. T. The Icon Programming Language. 2nd ed. PrenticeHall, Englewood Cliffs, N.J., 1990. HOFFMAN, C. M., AND ODONNELL, M. J. Pattern matching in trees. J. ACM 29, 1 (Jan. 1982), 68-95. PELEGRf-LLOPART, E. Tree transformation in compiler systems. Ph.D. thesis, Computer Science Division, Dept. of Electrical Engineering and Computer Science, Univ. of California, Berkeley, Calif., Dec. 1987. PELEGRf-LLOPART, E., AND GRAHAM, S. L. Optimal code generation for expression trees: An application
Programming SIGPLAN Not.

Record of the ACM S.wwsiu m on princwles of of BURS theory. In Conference Languages (San Diego, Calif., Jan. 13-15, 1988). ACM, New York, pp. 294-308. of the 18. PROEBSTING, T. A. Simple and efficient BURS table generation. In Proceedings 92 Conference on Programming Language SPEC Design Benchmark and Implementation. Suite Release SIGPLAN 1.0. Standards

(ACM) 27, 6 (June 1992), 331-340.


Evaluation Corp., Oct. 1989. 1993

19. STANDARDSPERFORMANCEEVALUATION CORP.


Performance Received October

1992; revised and accepted January

ACM Letters on Programming

Languages and Systems, Vol. 1, No 3, September 1992

Вам также может понравиться