introduction - cs.vu.nl · pdf fileprogram compiler txt txt x compiler exe exe y = =...

319
1 Introduction 1

Upload: vannga

Post on 30-Jan-2018

218 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

1�������������������������������������������������������������������������

Introduction

1

Page 2: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

Program

Compiler

txt

txt

X

Compiler

exe

exe

Y

=

=

Executable compilercode

Compiler source text

Input in

code for targetExecutable program

languagein implementation

in source languageProgram source text

some input format

machine

Output insome output format

Figure 1.1 Compiling and running a compiler.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

Compiler

txt

Sourcetext

Front-end

(analysis)

Semanticrepresent-

ation (synthesis)end

Back-exe

Executablecode

Figure 1.2 Conceptual structure of a compiler.� �����������������������������������������������������������������������������������������������

2 SECTION 1.1 Why study compiler construction?

Page 3: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

Sourcecode

ExecutableMachine

code

Interpreter

codeSource Intermediate

code

processingpreprocessing

processingpreprocessing

Compilation

Interpretation

Figure 1.3 Comparison of a compiler and an interpreter.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

L M

Language 1

Language 2

Back-ends forFront-ends for

Machine Language

Machine 2

Machine 1

Semanticrepresent-

ation

Figure 1.4 Creating compilers for L languages and M machines.� �����������������������������������������������������������������������������������������������

SUBSECTION 1.1.1 Compiler construction is very successful 3

Page 4: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

expression

identifier identifier

factor identifier factor identifier

term factor term factor identifier

term term factor

expression term

’*’

’b’

’b’

’4’

’a’

’c’

’*’

’*’

’-’

Figure 1.5 The expression b*b - 4*a*c as a parse tree.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

’b’ ’b’

’*’

’-’

’*’

’*’ ’c’

’a’’4’

Figure 1.6 The expression b*b - 4*a*c as an AST.� �����������������������������������������������������������������������������������������������

4 SECTION 1.2 A simple traditional modular compiler/interpreter

Page 5: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

type: realloc: sp+16

type: realloc: reg1

type: realloc: reg1

type: realloc: sp+16

type: realloc: const

type: realloc: sp+8

loc: reg2type: real type: real

loc: sp+24

type: realloc: reg2

’b’

’*’

’-’

’b’

’4’ ’a’

’c’’*’

’*’

Figure 1.7 The expression b*b - 4*a*c as an annotated AST.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

Syntaxanalysis

Lexicalanalysis

Code

Contexthandling

generation

Interpretation

code(AST)

Intermediate

Figure 1.8 Structure of the demo compiler/interpreter.� �����������������������������������������������������������������������������������������������

SUBSECTION 1.2.5 Syntax analysis for the demo compiler 5

Page 6: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

expression → digit | ’(’ expression operator expression ’)’operator → ’+’ | ’*’digit → ’0’ | ’1’ | ’2’ | ’3’ | ’4’ | ’5’ | ’6’ | ’7’ | ’8’ | ’9’

Figure 1.9 Grammar for simple fully parenthesized expressions.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

#include "parser.h" /* for type AST_node */#include "backend.h" /* for Process() */#include "error.h" /* for Error() */

int main(void) {AST_node *icode;

if (!Parse_program(&icode)) Error("No top-level expression");Process(icode);

return 0;}

Figure 1.10 Driver for the demo compiler.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

/* Define class constants *//* Values 0-255 are reserved for ASCII characters */#define EOF 256#define DIGIT 257

typedef struct {int class; char repr;} Token_type;

extern Token_type Token;extern void get_next_token(void);

Figure 1.11 Header file lex.h for the demo lexical analyzer.� �����������������������������������������������������������������������������������������������������������

6 SECTION 1.4 Compiler architectures

Page 7: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

#include "lex.h" /* for self check *//* PRIVATE */

static int Layout_char(int ch) {switch (ch) {case ’ ’: case ’\t’: case ’\n’: return 1;default: return 0;}

}/* PUBLIC */

Token_type Token;

void get_next_token(void) {int ch;

/* get a non-layout character: */do {

ch = getchar();if (ch < 0) {

Token.class = EOF; Token.repr = ’#’;return;

}} while (Layout_char(ch));

/* classify it: */if (’0’ <= ch && ch <= ’9’) {Token.class = DIGIT;}else {Token.class = ch;}

Token.repr = ch;}

Figure 1.12 Lexical analyzer for the demo compiler.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 1.4.1 The width of the compiler 7

Page 8: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

static int Parse_operator(Operator *oper) {if (Token.class == ’+’) {

*oper = ’+’; get_next_token(); return 1;}if (Token.class == ’*’) {

*oper = ’*’; get_next_token(); return 1;}return 0;

}

static int Parse_expression(Expression **expr_p) {Expression *expr = *expr_p = new_expression();

/* try to parse a digit: */if (Token.class == DIGIT) {

expr->type = ’D’; expr->value = Token.repr - ’0’;get_next_token();return 1;

}

/* try to parse a parenthesized expression: */if (Token.class == ’(’) {

expr->type = ’P’;get_next_token();if (!Parse_expression(&expr->left)) {

Error("Missing expression");}if (!Parse_operator(&expr->oper)) {

Error("Missing operator");}if (!Parse_expression(&expr->right)) {

Error("Missing expression");}if (Token.class != ’)’) {

Error("Missing )");}get_next_token();return 1;

}

/* failed on both attempts */free_expression(expr); return 0;

}

Figure 1.13 Parsing routines for the demo compiler.� �����������������������������������������������������������������������������������������������������������

8 SECTION 1.4 Compiler architectures

Page 9: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

#include "lex.h"#include "error.h" /* for Error() */#include "parser.h" /* for self check */

/* PRIVATE */static Expression *new_expression(void) {

return (Expression *)malloc(sizeof (Expression));}static void free_expression(Expression *expr) {free((void *)expr);}static int Parse_operator(Operator *oper_p);static int Parse_expression(Expression **expr_p);

/* PUBLIC */int Parse_program(AST_node **icode_p) {

Expression *expr;

get_next_token(); /* start the lexical analyzer */if (Parse_expression(&expr)) {

if (Token.class != EOF) {Error("Garbage after end of program");

}*icode_p = expr;return 1;

}return 0;

}

Figure 1.14 Parser environment for the demo compiler.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 1.4.2 Who’s the boss? 9

Page 10: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

int P(...) {/* try to parse the alternative A1 A2 ... An */if (A1(...)) {

if (!A2(...)) Error("Missing A2");...if (!An(...)) Error("Missing An");return 1;

}/* try to parse the alternative B1 B2 ... */if (B1(...)) {

if (!B2(...)) Error("Missing B2");...return 1;

}.../* failed to find any alternative of P */return 0;

}

Figure 1.15 A C template for a grammar rule.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

typedef int Operator;

typedef struct _expression {char type; /* ’D’ or ’P’ */int value; /* for ’D’ */struct _expression *left, *right; /* for ’P’ */Operator oper; /* for ’P’ */

} Expression;

typedef Expression AST_node; /* the top node is an Expression */

extern int Parse_program(AST_node **);

Figure 1.16 Parser header file for the demo compiler.� �����������������������������������������������������������������������������������������������������������

10 CHAPTER 1 Introduction

Page 11: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

’D’

’D’ ’D’

’D’

type

oper

value

’P’

’P’

’P’

*

*

+2

3 4

9

left right

Figure 1.17 An AST for the expression (2*((3*4)+9)).� �����������������������������������������������������������������������������������������������

SECTION 1.10 Closure algorithms 11

Page 12: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

#include "parser.h" /* for types AST_node and Expression */#include "backend.h" /* for self check */

/* PRIVATE */static void Code_gen_expression(Expression *expr) {

switch (expr->type) {case ’D’:

printf("PUSH %d\n", expr->value);break;

case ’P’:Code_gen_expression(expr->left);Code_gen_expression(expr->right);switch (expr->oper) {case ’+’: printf("ADD\n"); break;case ’*’: printf("MULT\n"); break;}break;

}}

/* PUBLIC */void Process(AST_node *icode) {

Code_gen_expression(icode); printf("PRINT\n");}

Figure 1.18 Code generation back-end for the demo compiler.� �����������������������������������������������������������������������������������������������������������

12 CHAPTER 1 Introduction

Page 13: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

#include "parser.h" /* for types AST_node and Expression */#include "backend.h" /* for self check */

/* PRIVATE */static int Interpret_expression(Expression *expr) {

switch (expr->type) {case ’D’:

return expr->value;break;

case ’P’: {int e_left = Interpret_expression(expr->left);int e_right = Interpret_expression(expr->right);switch (expr->oper) {case ’+’: return e_left + e_right;case ’*’: return e_left * e_right;}}break;

}}

/* PUBLIC */void Process(AST_node *icode) {

printf("%d\n", Interpret_expression(icode));}

Figure 1.19 Interpreter back-end for the demo compiler.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

extern void Process(AST_node *);

Figure 1.20 Common back-end header for code generator and interpreter.� �����������������������������������������������������������������������������������������������������������

SECTION 1.10 Closure algorithms 13

Page 14: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

Lexical

Context

Syntax

Intermediate

Program

Code

Executable

Machine

Target

textinput

codegeneration

codeoptimization

codegeneration

codeoutput

analysis

analysis

handling

generation

file file

Front-end Back-end

IC

IC

characters

tokens

AST

annotated AST bit patterns

IC

optimizationIC

symbolic instructions

Intermediate

symbolic instructions

code

Figure 1.21 Structure of a compiler.� �����������������������������������������������������������������������������������������������

14 CHAPTER 1 Introduction

Page 15: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

SET Object code TOAssembly(

Code generation(Context check(

Parse(Tokenize(

Source code)

))

));

Figure 1.22 Flow-of-control structure of a broad compiler.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

WHILE NOT Finished:Read some data D from the source code;Process D and produce the corresponding object code, if any;

Figure 1.23 Flow-of-control structure of a narrow compiler.� �����������������������������������������������������������������������������������������������������������

SECTION 1.12 Conclusion 15

Page 16: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

WHILE Obtained input character Ch from previous module:IF Ch = ’a’:

// See if there is another ’a’:IF Obtained input character Ch1 from previous module:

IF Ch1 = ’a’:// We have ’aa’:Output character ’b’ to next module;

ELSE Ch1 /= ’a’:Output character ’a’ to next module;Output character Ch1 to next module;

ELSE Ch1 not obtained:Output character ’a’ to next module;EXIT WHILE;

ELSE Ch /= ’a’:Output character Ch to next module;

Figure 1.24 The filter aa → b as a main loop.� �����������������������������������������������������������������������������������������������������������

16 CHAPTER 1 Introduction

Page 17: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

SET the flag Input exhausted TO False;SET the flag There is a stored character TO False;SET Stored character TO Undefined; // can never be an ’a’

FUNCTION Filtered character RETURNING a Boolean, a character:IF Input Exhausted: RETURN False, No character;ELSE IF There is a stored character:

// It cannot be an ’a’:SET There is a stored character TO False;RETURN True, Stored character;

ELSE Input not exhausted AND There is no stored character:IF Obtained input character Ch from previous module:

IF Ch = ’a’:// See if there is another ’a’:IF Obtained input character Ch1 from previous module:

IF Ch1 = ’a’:// We have ’aa’:RETURN True, ’b’;

ELSE Ch1 /= ’a’:SET Stored character TO Ch1;SET There is a stored character TO True;RETURN True, ’a’;

ELSE Ch1 not obtained:SET Input exhausted TO True;RETURN True, ’a’;

ELSE Ch /= ’a’:RETURN True, Ch;

ELSE Ch not obtained:SET Input exhausted TO True;RETURN False, No character;

Figure 1.25 The filter aa → b as a pre-main module.� �����������������������������������������������������������������������������������������������������������

SECTION 1.12 Conclusion 17

Page 18: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

expression1@1 ’(’ expression operator expression ’)’2@2 ’(’ ’1’ operator expression ’)’4@3 ’(’ ’1’ ’*’ expression ’)’1@4 ’(’ ’1’ ’*’ ’(’ expression operator expression ’)’ ’)’2@5 ’(’ ’1’ ’*’ ’(’ ’1’ operator expression ’)’ ’)’3@6 ’(’ ’1’ ’*’ ’(’ ’1’ ’+’ expression ’)’ ’)’2@7 ’(’ ’1’ ’*’ ’(’ ’1’ ’+’ ’1’ ’)’ ’)’

Figure 1.26 Leftmost derivation of the string (1*(1+1)).� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

expression

’1’’+’’1’

’)’expressionoperatorexpression’(’

expression ’)’

’*’’1’

expression operator’(’

Figure 1.27 Parse tree of the derivation in Figure 1.26.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

void P() { ... Q(); .... S(); ... }void Q() { ... R(); .... T(); ... }void R() { ... P(); }void S() { ... }void T() { ... }

Figure 1.28 Sample C program used in the construction of a calling graph.� �����������������������������������������������������������������������������������������������������������

18 CHAPTER 1 Introduction

Page 19: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

P

Q S

R T

Figure 1.29 Initial (direct) calling graph of the code in Figure 1.28.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

P

Q S

R T

Figure 1.30 Calling graph of the code in Figure 1.28.� �����������������������������������������������������������������������������������������������

SECTION 1.12 Conclusion 19

Page 20: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

Data definitions:1. Let G be a directed graph with one node for each routine. The informationitems are arrows in G.2. An arrow from a node A to a node B means that routine A calls routine Bdirectly or indirectly.

Initializations:If the body of a routine A contains a call to routine B, an arrow from A to Bmust be present.

Inference rules:If there is an arrow from node A to node B and one from B to C, an arrow fromA to C must be present.

Figure 1.31 Recursion detection as a closure algorithm.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

calls(A, C) :- calls(A, B), calls(B, C).calls(a, b).calls(b, a).:-? calls(a, a).

Figure 1.32 A Prolog program corresponding to the closure algorithm of Figure 1.31.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

SET the flag Something changed TO True;

WHILE Something changed:SET Something changed TO False;

FOR EACH Node 1 IN Graph:FOR EACH Node 2 IN Descendants of Node 1:

FOR EACH Node 3 IN Descendants of Node 2:IF there is no arrow from Node 1 to Node 3:

Add an arrow from Node 1 to Node 3;SET Something changed TO True;

Figure 1.33 Outline of a bottom-up algorithm for transitive closure.� �����������������������������������������������������������������������������������������������������������

20 CHAPTER 1 Introduction

Page 21: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

2�������������������������������������������������������������������������

From program text toabstract syntax tree

21

Page 22: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

expression → product | factorproduct → expression ’*’ factorfactor → number | identifier

Figure 2.1 A very simple grammar for expression.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

if_statement

conditionIF THEN statement

if_statement

condition statement statement

(b)(a)

Figure 2.2 Syntax tree (a) and abstract syntax tree (b) of an if-then statement.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

Inputtext

Lexicalanalysis

Syntaxanalysis

Contexthandling

AnnotatedAST

tokens AST ASTchars

Figure 2.3 Pipeline from input to annotated syntax tree.� �����������������������������������������������������������������������������������������������

22 SECTION 2.1 From program text to tokens − the lexical structure

Page 23: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

Basic patterns: Matching:x The character x. Any character, usually except a newline[xyz...] Any of the characters x, y, z, ...

Repetition operators:R ? An R or nothing (= optionally an R)R* Zero or more occurrences of RR + One or more occurrences of R

Composition operators:R 1R 2 An R 1 followed by an R 2

R 1 |R 2 Either an R 1 or an R 2

Grouping:(R) R itself

Figure 2.4 Components of regular expressions.� �����������������������������������������������������������������������������������������������

SUBSECTION 2.1.5 Creating a lexical analyzer by hand 23

Page 24: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

/* Define class constants; 0-255 reserved for ASCII characters: */#define EOF 256#define IDENTIFIER 257#define INTEGER 258#define ERRONEOUS 259

typedef struct {char *file_name;int line_number;int char_number;

} Position_in_File;

typedef struct {int class;char *repr;Position_in_File pos;

} Token_Type;

extern Token_Type Token;

extern void start_lex(void);extern void get_next_token(void);

Figure 2.5 Header file lex.h of the handwritten lexical analyzer.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

#include "input.h" /* for get_input() */#include "lex.h"

/* PRIVATE */static char *input;static int dot; /* dot position in input */static int input_char; /* character at dot position */

#define next_char() (input_char = input[++dot])

/* PUBLIC */Token_Type Token;

void start_lex(void) {input = get_input();dot = 0; input_char = input[dot];

}

Figure 2.6 Data and start-up of the handwritten lexical analyzer.� �����������������������������������������������������������������������������������������������������������

24 SECTION 2.1 From program text to tokens − the lexical structure

Page 25: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

void get_next_token(void) {int start_dot;

skip_layout_and_comment();/* now we are at the start of a token or at end-of-file, so: */note_token_position();

/* split on first character of the token */start_dot = dot;if (is_end_of_input(input_char)) {

Token.class = EOF; Token.repr = "<EOF>"; return;}if (is_letter(input_char)) {recognize_identifier();}elseif (is_digit(input_char)) {recognize_integer();}elseif (is_operator(input_char) || is_separator(input_char)) {

Token.class = input_char; next_char();}else {Token.class = ERRONEOUS; next_char();}

Token.repr = input_to_zstring(start_dot, dot-start_dot);}

Figure 2.7 Main reading routine of the handwritten lexical analyzer.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

void skip_layout_and_comment(void) {while (is_layout(input_char)) {next_char();}while (is_comment_starter(input_char)) {

next_char();while (!is_comment_stopper(input_char)) {

if (is_end_of_input(input_char)) return;next_char();

}next_char();while (is_layout(input_char)) {next_char();}

}}

Figure 2.8 Skipping layout and comment in the handwritten lexical analyzer.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 2.1.5 Creating a lexical analyzer by hand 25

Page 26: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

void recognize_identifier(void) {Token.class = IDENTIFIER; next_char();

while (is_letter_or_digit(input_char)) {next_char();}

while (is_underscore(input_char)&& is_letter_or_digit(input[dot+1])) {

next_char();while (is_letter_or_digit(input_char)) {next_char();}

}}

Figure 2.9 Recognizing an identifier in the handwritten lexical analyzer.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

void recognize_integer(void) {Token.class = INTEGER; next_char();while (is_digit(input_char)) {next_char();}

}

Figure 2.10 Recognizing an integer in the handwritten lexical analyzer.� �����������������������������������������������������������������������������������������������������������

26 SECTION 2.1 From program text to tokens − the lexical structure

Page 27: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

#define is_end_of_input(ch) ((ch) == ’\0’)#define is_layout(ch) (!is_end_of_input(ch) && (ch) <= ’ ’)#define is_comment_starter(ch) ((ch) == ’#’)#define is_comment_stopper(ch) ((ch) == ’#’ || (ch) == ’\n’)

#define is_uc_letter(ch) (’A’ <= (ch) && (ch) <= ’Z’)#define is_lc_letter(ch) (’a’ <= (ch) && (ch) <= ’z’)#define is_letter(ch) (is_uc_letter(ch) || is_lc_letter(ch))#define is_digit(ch) (’0’ <= (ch) && (ch) <= ’9’)#define is_letter_or_digit(ch) (is_letter(ch) || is_digit(ch))#define is_underscore(ch) ((ch) == ’_’)

#define is_operator(ch) (strchr("+-*/", (ch)) != 0)#define is_separator(ch) (strchr(";,(){}", (ch)) != 0)

Figure 2.11 Character classification in the handwritten lexical analyzer.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

#include "lex.h" /* for start_lex(), get_next_token() */

int main(void) {start_lex();

do {get_next_token();switch (Token.class) {case IDENTIFIER: printf("Identifier"); break;case INTEGER: printf("Integer"); break;case ERRONEOUS: printf("Erroneous token"); break;case EOF: printf("End-of-file pseudo-token"); break;default: printf("Operator or separator"); break;}printf(": %s\n", Token.repr);

} while (Token.class != EOF);return 0;

}

Figure 2.12 Driver for the handwritten lexical analyzer.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 2.1.6 Creating a lexical analyzer automatically 27

Page 28: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

Integer: 8Operator or separator: ;Identifier: abcErroneous token: _Erroneous token: _Identifier: dd_8Operator or separator: ;Identifier: zzErroneous token: _End-of-file pseudo-token: <EOF>

Figure 2.13 Sample results of the hand-written lexical analyzer.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

#define is_operator(ch) (is_operator_bit[(ch)&0377])

static const char is_operator_bit[256] = {0, /* position 0 */0, 0, ... /* another 41 zeroes */1, /* ’*’, position 42 */1, /* ’+’ */0,1, /* ’-’ */0,1, /* ’/’, position 47 */0, 0, ... /* 208 more zeroes */

};

Figure 2.14 A naive table implementation of is_operator().� �����������������������������������������������������������������������������������������������������������

28 SECTION 2.1 From program text to tokens − the lexical structure

Page 29: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

#define UC_LETTER_MASK (1<<1) /* a 1 bit, shifted left 1 pos. */#define LC_LETTER_MASK (1<<2) /* a 1 bit, shifted left 2 pos. */#define OPERATOR_MASK (1<<5)

#define LETTER_MASK (UC_LETTER_MASK | LC_LETTER_MASK)

#define bits_of(ch) (charbits[(ch)&0377])

#define is_end_of_input(ch) ((ch) == ’\0’)

#define is_uc_letter(ch) (bits_of(ch) & UC_LETTER_MASK)#define is_lc_letter(ch) (bits_of(ch) & LC_LETTER_MASK)#define is_letter(ch) (bits_of(ch) & LETTER_MASK)

#define is_operator(ch) (bits_of(ch) & OPERATOR_MASK)

static const char charbits[256] = {0000, /* position 0 */...0040, /* ’*’, position 42 */0040, /* ’+’ */...0000, /* position 64 */0002, /* ’A’ */0002, /* ’B’ */

0000, /* position 96 */0004, /* ’a’ */0004, /* ’b’ */...0000 /* position 255 */

};

Figure 2.15 Efficient classification of characters (excerpt).� �����������������������������������������������������������������������������������������������������������

SUBSECTION 2.1.6 Creating a lexical analyzer automatically 29

Page 30: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

SET the global token (Token .class, Token .length) TO (0, 0);

// Try to match token description T1→R1:FOR EACH Length SUCH THAT the input matches T1→R1 over Length:

IF Length > Token .length:SET (Token .class, Token .length) TO (T1, Length);

// Try to match token description T2→R2:FOR EACH Length SUCH THAT the input matches T2→R2 over Length:

IF Length > Token .length:SET (Token .class, Token .length) TO (T2, Length);

...

FOR EACH Length SUCH THAT the input matches Tn→Rn over Length:IF Length > Token .length:

SET (Token .class, Token .length) TO (Tn, Length);

IF Token .length = 0:Handle non-matching character;

Figure 2.16 Outline of a naive generated lexical analyzer.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

regular expression

input

gap

Alreadymatched

Still to bematched

Figure 2.17 Components of a token description and components of the input.� �����������������������������������������������������������������������������������������������

30 SECTION 2.1 From program text to tokens − the lexical structure

Page 31: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

α βbyby

input

Dotted item

T α β

Already matched Still to be matched

nc c n+1

Figure 2.18 The relation between a dotted item and the input.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

T→α � (R)*β ⇒ T→α(R)* � βT→α( � R)*β

T→α(R � )*β ⇒ T→α(R)* � βT→α( � R)*β

T→α � (R)+β ⇒ T→α( � R)+β

T→α(R � )+β ⇒ T→α(R)+ � βT→α( � R)+β

T→α � (R)?β ⇒ T→α(R)? � βT→α( � R)?β

T→α(R � )?β ⇒ T→α(R)? � β

T→α � (R 1 | R 2 | ...)β ⇒ T→α( � R 1 | R 2 | ...)βT→α(R 1 | � R 2 | ...)β...

T→α(R 1� | R 2 | ...)β ⇒ T→α(R 1 | R 2 | ...) � β

T→α(R 1 | R 2� | ...)β ⇒ T→α(R 1 | R 2 | ...) � β

... ... ...

Figure 2.19 ε move rules for the regular operators.� �����������������������������������������������������������������������������������������������

SUBSECTION 2.1.6 Creating a lexical analyzer automatically 31

Page 32: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

integral_number → [0-9]+fixed_point_number → [0-9]*’.’[0-9]+

Figure 2.20 A simple set of regular expressions.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

IMPORT Input char [1..]; // as from the previous moduleSET Read index TO 1; // the read index into Input char []

PROCEDURE Get next token:SET Start of token TO Read index;SET End of last token TO Uninitialized;SET Class of last token TO Uninitialized;

SET Item set TO Initial item set ();WHILE Item set /= Empty:

SET Ch TO Input char [Read index];SET Item set TO Next item set (Item set, Ch);SET Class TO Class of token recognized in (Item set);IF Class /= No class:

SET Class of last token TO Class;SET End of last token TO Read index;

SET Read index TO Read index + 1;

SET Token .class TO Class of last token;SET Token .repr TO Input char [Start of token .. End of last token];SET Read index TO End of last token + 1;

Figure 2.21 Outline of a linear-time lexical analyzer.� �����������������������������������������������������������������������������������������������������������

32 SECTION 2.1 From program text to tokens − the lexical structure

Page 33: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

FUNCTION Initial item set RETURNING an item set:SET New item set TO Empty;

// Initial contents - obtain from the language specification:FOR EACH token description T→R IN the language specification:

SET New item set TO New item set + item T→ � R;

RETURN ε closure (New item set);

Figure 2.22 The function Initial item set for a lexical analyzer.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

FUNCTION Next item set (Item set, Ch) RETURNING an item set:SET New item set TO Empty;

// Initial contents - obtain from character moves:FOR EACH item T→α � Bβ IN Item set:

IF B is a basic pattern AND B matches Ch:SET New item set TO New item set + item T→αB � β;

RETURN ε closure (New item set);

Figure 2.23 The function Next item set() for a lexical analyzer.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

FUNCTION ε closure (Item set) RETURNING an item set:SET Closure set TO the Closure set produced by the

closure algorithm 2.25, passing the Item set to it;

// Filter out the interesting items:SET New item set TO Empty set;FOR EACH item I IN Closure set:

IF I is a basic item:Insert I in New item set;

RETURN New item set;

Figure 2.24 The function ε closure() for a lexical analyzer.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 2.1.7 Transition table compression 33

Page 34: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

Data definitions:Let Closure set be a set of dotted items.

Initializations:Put each item in Item set in Closure set.

Inference rules:If an item in Closure set matches the left-hand side of one of the ε movesin Figure 2.19, the corresponding right-hand side must be present in Closureset.

Figure 2.25 Closure algorithm for dotted items.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

Data definitions:1a. A ‘state’ is a set of items.1b. Let States be a set of states.2a. A ‘state transition’ is a triple (start state, character, end state).2b. Let Transitions be a set of state transitions.

Initializations:1. Set States to contain a single state, Initial item set().2. Set Transitions to the empty set.

Inference rules:If States contains a state S, States must contain the state E and Transi-tions must contain the state transition (S, Ch, E) for each character Ch inthe input character set, where E = Next item set (S, Ch).

Figure 2.26 The subset algorithm for lexical analyzers.� �����������������������������������������������������������������������������������������������

34 SECTION 2.1 From program text to tokens − the lexical structure

Page 35: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

Next state [] Class of token recognized in[]State Ch

digit point otherS 0 S 1 S 2 - -S 1 S 1 S 2 - integral_numberS 2 S 3 - - -S 3 S 3 - - fixed_point_number

Figure 2.27 Transition table and recognition table for the regular expressions from Figure 2.20.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

2

S0

S1

S3

S

F->(D)*.’.’(D)+

’.’

D

F->(D)*’.’(.D)+

F->(.D)*’.’(D)+I->(.D)+

F->(D)*.’.’(D)+F->(.D)*’.’(D)+I->(D)+ .I->(.D)+

D!F->(D)*’.’(.D)+F->(D)*’.’(D)+.

D

D

’.’

!

Figure 2.28 Transition diagram of the states and transitions for Figure 2.20.� �����������������������������������������������������������������������������������������������

SUBSECTION 2.1.7 Transition table compression 35

Page 36: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

PROCEDURE Get next token:SET Start of token TO Read index;SET End of last token TO Uninitialized;SET Class of last token TO Uninitialized;

SET Item set TO Initial item set;WHILE Item set /= Empty:

SET Ch TO Input char [Read index];SET Item set TO Next item set [Item set, Ch];SET Class TO Class of token recognized in [Item set];IF Class /= No class:

SET Class of last token TO Class;SET End of last token TO Read index;

SET Read index TO Read index + 1;

SET Token .class TO Class of last token;SET Token .repr TO Input char [Start of token .. End of last token];SET Read index TO End of last token + 1;

Figure 2.29 Outline of an efficient linear-time routine Get next token().� �����������������������������������������������������������������������������������������������������������

36 SECTION 2.1 From program text to tokens − the lexical structure

Page 37: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

0S

1

S3

2

S

S

F->(D)*.’.’(D)+

’.’

D

F->(D)*’.’(.D)+

F->(.D)*’.’(D)+I->(.D)+

F->(D)*.’.’(D)+F->(.D)*’.’(D)+I->(D)+ .I->(.D)+

D!F->(D)*’.’(.D)+F->(D)*’.’(D)+.

D

D’.’’.’

other other

’.’

!

other other

Figure 2.30 Transition diagram of all states and transitions for Figure 2.20.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

state digit=1 other=2 point=30 1 - 21 1 - 22 3 - -3 3 - -

Figure 2.31 The transition matrix from Figure 2.27 in reduced form.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 2.1.9 A traditional lexical analyzer generator − lex 37

Page 38: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

0 1 - 21 1 - 22 3 - -3 3 - -

� �����������������������������

1 3 2 -

Figure 2.32 Fitting the strips into one array.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

Empty state [0..3][1..3] =((0, 1, 0), (0, 1, 0), (0, 1, 1), (0, 1, 1));

Displacement [0..3] = (0, 0, 1, 1);Entry [1..3] = (1, 3, 2);

Figure 2.33 The transition matrix from Figure 2.27 in compressed form.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

IF Empty state [State][Ch]:SET New state TO No state;

ELSE entry in Entry [] is valid:SET New state TO Entry [Displacement [State] + Ch];

Figure 2.34 Code for SET New state TO Next state[State, Ch].� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

0 (1, 1) - (2, 3)1 (1, 1) - (2, 3)2 (3, 1) - -3 (3, 1) - -

�����������������������������������������������������������������������������������������������������������������������������������������

(1, 1) (1, 1) (2, 3) (2, 3) (3, 1) (3, 1) - -

Figure 2.35 Fitting the strips with entries marked by character.� �����������������������������������������������������������������������������������������������������������

38 SECTION 2.1 From program text to tokens − the lexical structure

Page 39: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

Displacement [0..3] = (0, 1, 4, 5);Mark [1..8] = (1, 1, 3, 3, 1, 1, 0, 0);Entry [1..6] = (1, 1, 2, 2, 3, 3);

Figure 2.36 The transition matrix compressed with marking by character.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

IF Mark [Displacement [State] + Ch] /= Ch:SET New state TO No state;

ELSE entry in Entry [] is valid:SET New state TO Entry [Displacement [State] + Ch];

Figure 2.37 Code for SET New state TO Next state[State, Ch] for marking by character.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

0 1 1 1 1 1 0 1 0 0 1 1 0 0 1 0 1 0 0 1 0 0 0 10100 0 11

10100001

1

Figure 2.38 A damaged comb finding room for its teeth.� �����������������������������������������������������������������������������������������������

SUBSECTION 2.1.12 Macro processing and file inclusion 39

Page 40: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

w x y z w x y z w x y z0 1 2 - - 0 1 2 - -1 3 - 4 - 1 3 - 4 -2 1 - - 6 2 1 - - 63 - 2 - - 3 - 2 - -4 - - - 5 4 - - - 55 1 - 4 - 5 1 - 4 -6 - 7 - - 6 - 7 - -7 - - - - 7 - - - -

_______ _______1 2 4 6 3 7 4 5

(a) (b)

Figure 2.39 A transition table (a) and its compressed form packed by graph coloring (b).� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

0

1 6

2 5 3

4 7

Figure 2.40 Interference graph for the automaton of Figure 2.39a.� �����������������������������������������������������������������������������������������������

40 SECTION 2.2 From tokens to syntax tree − the syntax

Page 41: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

%{#include "lex.h"

Token_Type Token;int line_number = 1;%}

whitespace [ \t]

letter [a-zA-Z]digit [0-9]underscore "_"letter_or_digit ({letter}|{digit})underscored_tail ({underscore}{letter_or_digit}+)identifier ({letter}{letter_or_digit}*{underscored_tail}*)

operator [-+*/]separator [;,(){}]

%%

{digit}+ {return INTEGER;}{identifier} {return IDENTIFIER;}{operator}|{separator} {return yytext[0];}#[ˆ#\n]*#? {/* ignore comment */}{whitespace} {/* ignore whitespace */}\n {line_number++;}. {return ERRONEOUS;}

%%

void start_lex(void) {}

void get_next_token(void) {Token.class = yylex();if (Token.class == 0) {

Token.class = EOF; Token.repr = "<EOF>"; return;}Token.pos.line_number = line_number;strcpy(Token.repr = (char*)malloc(strlen(yytext)+1), yytext);

}

int yywrap(void) {return 1;}

Figure 2.41 Lex input for the token set from Figure 2.20.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 2.2.1 Two classes of parsing methods 41

Page 42: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

FUNCTION Get next token () RETURNING a token:SET Simple token TO Get next simple token ();IF Class of Simple token = Identifier:

SET Simple token TO Identify in symbol table (Simple token);// See if this has reset Class of Simple token:IF Class of Simple token = Macro:

Switch to macro (Simple token);RETURN Get next token ();

ELSE Class of Simple token /= Macro:// Identifier or Type identifier or Keyword:RETURN Simple token;

ELSE Class of Simple token /= Identifier:RETURN Simple token;

Figure 2.42 A Get next token() that does lexical identification.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

Programreadingmodule

Lexicalanalyzer

module

Lexicalidentification

Figure 2.43 Pipeline from input to lexical identification.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

FUNCTION Identify (Identifier name)RETURNING a pointer to Identifier info:SET Bucket number TO Hash value (Identifier name);IF there is no Identifier info record for Identifier name

in Bucket [Bucket number]:Insert an empty Identifier info record for Identifier name

in Bucket [Bucket number];RETURN Pointer to Identifier info record for Identifier name

in Bucket [Bucket number];

Figure 2.44 Outline of the function Identify.� �����������������������������������������������������������������������������������������������������������

42 SECTION 2.2 From tokens to syntax tree − the syntax

Page 43: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

idf_next

char[]idf_name

l e n g t h \0

idf_next idf_next

w i d t h \0 h e i g h t \0

char[]

idf_name idf_name

bucket 0

bucket 1

bucket 2

bucket 3

bucket 4

hash_table

struct idf

struct idf struct idf

Figure 2.45 A hash table of size 5 containing three identifiers.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

FUNCTION Identify in symbol table (Token) RETURNING a token:SET Identifier info pointer TO Identify (Representation of Token);IF Identifier info indicates macro:

SET Class of Token TO Macro;ELSE IF Identifier info indicates keyword:

SET Class of Token TO Keyword;ELSE IF Identifier info indicates type identifier:

SET Class of Token TO Type identifier;ELSE Identifier info indicates

variable, struct, union, etc. identifier:// Do not change Class of Token;

Append Identifier info pointer to Token;RETURN Token;

Figure 2.46 A possible Identify in symbol table(Token) for C.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 2.2.1 Two classes of parsing methods 43

Page 44: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

Programreadingmodule

Lexicalanalyzer

module

Lexicalidentification

back-calls

Figure 2.47 Pipeline from input to lexical identification, with feedback.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

readptr

readptr

readptr

readptr

file

endptr

file

macro

parameter

endptr

endptr

mac.h

input.c

is_capital

chdevelopment of

parameter list

t x t [ i ]

( ’ A ’ < = ( c h ) & & ( c h ) < = ’ Z ’ )

. . . . i s _ c a p i t a l ( t x t [ i ] ) . . . . .

. . . . # i n c l u d e " m a c . h " . . . .

ch = txt[i]

endptr

Figure 2.48 An input buffer stack of include files, macro calls, and macro parameters.� �����������������������������������������������������������������������������������������������

44 SECTION 2.2 From tokens to syntax tree − the syntax

Page 45: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

Lexicalanalyzer

module

Lexicalidentification

Programreadingmodule

Line-layermodule

back-calls

Figure 2.49 Input pipeline, with line layer and feedback.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

3

4 5

1

2 1

2 3

4

5

(a) Pre-order (b) Post-order

Figure 2.50 A tree with its nodes numbered in pre-order and post-order.� �����������������������������������������������������������������������������������������������

SUBSECTION 2.2.4 Creating a top-down parser automatically 45

Page 46: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

3t t t981t

input

t t2 t4 t 6 7

tree

t

parse

5

2

3

4

5

1

Figure 2.51 A top-down parser recognizing the first token in the input.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

3t t t t981t

input

2 tt t4 5 6 7

treeparse

t

3

1 2

Figure 2.52 A bottom-up parser constructing its first, second, and third nodes.� �����������������������������������������������������������������������������������������������

46 SECTION 2.2 From tokens to syntax tree − the syntax

Page 47: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

input → expression EOFexpression → term rest_expressionterm → IDENTIFIER | parenthesized_expressionparenthesized_expression → ’(’ expression ’)’rest_expression → ’+’ expression | ε

Figure 2.53 A simple grammar for demonstrating top-down parsing.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

#include "tokennumbers.h"

/* PARSER */int input(void) {

return expression() && require(token(EOF));}

int expression(void) {return term() && require(rest_expression());

}

int term(void) {return token(IDENTIFIER) || parenthesized_expression();

}

int parenthesized_expression(void) {return token(’(’) && require(expression()) && require(token(’)’));

}

int rest_expression(void) {return token(’+’) && require(expression()) || 1;

}

int token(int tk) {if (tk != Token.class) return 0;get_next_token(); return 1;

}

int require(int found) {if (!found) error();return 1;

}

Figure 2.54 A recursive descent parser/recognizer for the grammar of Figure 2.53.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 2.2.4 Creating a top-down parser automatically 47

Page 48: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

#include "lex.h" /* for start_lex(), get_next_token(), Token */

/* DRIVER */int main(void) {

start_lex(); get_next_token();require(input());return 0;

}

void error(void) {printf("Error in expression\n"); exit(1);

}

Figure 2.55 Driver for the recursive descent parser/recognizer.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

S → A ’a’ ’b’A → ’a’ | ε

Figure 2.56 A simple grammar with a FIRST/FOLLOW conflict.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

int S(void) {return A() && require(token(’a’)) && require(token(’b’));

}

int A(void) {return token(’a’) || 1;

}

Figure 2.57 A faulty recursive recognizer for grammar of Figure 2.56.� �����������������������������������������������������������������������������������������������������������

48 SECTION 2.2 From tokens to syntax tree − the syntax

Page 49: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

Data definitions:1. Token sets called FIRST sets for all terminals, non-terminals and alterna-tives of non-terminals in G.2. A token set called FIRST for each alternative tail in G; an alternative tail isa sequence of zero or more grammar symbols α if Aα is an alternative or alter-native tail in G.

Initializations:1. For all terminals T, set FIRST(T) to {T}.2. For all non-terminals N, set FIRST(N) to the empty set.3. For all non-empty alternatives and alternative tails α, set FIRST(α) to theempty set.4. Set the FIRST set of all empty alternatives and alternative tails to {ε}.

Inference rules:1. For each rule N→α in G, FIRST(N) must contain all tokens in FIRST(α),including ε if FIRST(α) contains it.2. For each alternative or alternative tail α of the form Aβ, FIRST(α) mustcontain all tokens in FIRST(A), excluding ε, should FIRST(A) contain it.3. For each alternative or alternative tail α of the form Aβ and FIRST(A) con-tains ε, FIRST(α) must contain all tokens in FIRST(β), including ε ifFIRST(β) contains it.

Figure 2.58 Closure algorithm for computing the FIRST sets in a grammar G.� �����������������������������������������������������������������������������������������������

SUBSECTION 2.2.4 Creating a top-down parser automatically 49

Page 50: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

Rule/alternative (tail) FIRST setinput {}

expression EOF {}EOF { EOF }

expression {}term rest_expression {}

rest_expression {}

term {}IDENTIFIER { IDENTIFIER }

|parenthesized_expression {}

parenthesized_expression {}’(’ expression ’)’ { ’(’ }

expression ’)’ {}’)’ { ’)’ }

rest_expression {}’+’ expression { ’+’ }

expression {}| ε { ε }

Figure 2.59 The initial FIRST sets.� �����������������������������������������������������������������������������������������������������������

50 SECTION 2.2 From tokens to syntax tree − the syntax

Page 51: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

Rule/alternative (tail) FIRST setinput { IDENTIFIER ’(’ }

expression EOF { IDENTIFIER ’(’ }EOF { EOF }

expression { IDENTIFIER ’(’ }term rest_expression { IDENTIFIER ’(’ }

rest_expression { ’+’ ε }

term { IDENTIFIER ’(’ }IDENTIFIER { IDENTIFIER }

|parenthesized_expression { ’(’ }

parenthesized_expression { ’(’ }’(’ expression ’)’ { ’(’ }

expression ’)’ { IDENTIFIER ’(’ }’)’ { ’)’ }

rest_expression { ’+’ ε }’+’ expression { ’+’ }

expression { IDENTIFIER ’(’ }| ε { ε }

Figure 2.60 The final FIRST sets.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 2.2.4 Creating a top-down parser automatically 51

Page 52: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

void input(void) {switch (Token.class) {case IDENTIFIER: case ’(’:

expression(); token(EOF); break;default: error();}

}

void expression(void) {switch (Token.class) {case IDENTIFIER: case ’(’:

term(); rest_expression(); break;default: error();}

}

void term(void) {switch (Token.class) {case IDENTIFIER: token(IDENTIFIER); break;case ’(’: parenthesized_expression(); break;default: error();}

}

void parenthesized_expression(void) {switch (Token.class) {case ’(’: token(’(’); expression(); token(’)’); break;default: error();}

}

void rest_expression(void) {switch (Token.class) {case ’+’: token(’+’); expression(); break;case EOF: case ’)’: break;default: error();}

}

void token(int tk) {if (tk != Token.class) error();get_next_token();

}

Figure 2.61 A predictive parser for the grammar of Figure 2.53.� �����������������������������������������������������������������������������������������������������������

52 SECTION 2.2 From tokens to syntax tree − the syntax

Page 53: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

Data definitions:1. Token sets called FOLLOW sets for all non-terminals in G.2. Token sets called FIRST sets for all alternatives and alternative tails in G.

Initializations:1. For all non-terminals N, set FOLLOW(N) to the empty set.2. Set all FIRST sets to the values determined by the algorithm for FIRST sets.

Inference rules:1. For each rule of the form M→αNβ in G, FOLLOW(N) must contain alltokens in FIRST(β), excluding ε, should FIRST(β) contain it.2. For each rule of the form M→αNβ in G where FIRST(β) contains ε,FOLLOW(N) must contain all tokens in FOLLOW(M).

Figure 2.62 Closure algorithm for computing the FOLLOW sets in grammar G.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

Rule FIRST set FOLLOW setinput { IDENTIFIER ’(’ } {}expression { IDENTIFIER ’(’ } { EOF ’)’ }term { IDENTIFIER ’(’ } { ’+’ EOF ’)’ }parenthesized_expression { ’(’ } { ’+’ EOF ’)’ }rest_expression { ’+’ ε } { EOF ’)’ }

Figure 2.63 The FIRST and FOLLOW sets for the grammar from Figure 2.53.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 2.2.4 Creating a top-down parser automatically 53

Page 54: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

void S(void) {switch (Token.class) {case ’a’: A(); token(’a’); token(’b’); break;default: error();}

}

void A(void) {switch (Token.class) {case ’a’: token(’a’); break;case ’a’: break;default: error();}

}

Figure 2.64 A predictive parser for the grammar of Figure 2.56.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

Top of stack/state: Look-ahead tokenIDENTIFIER + ( ) EOF

� ���������������������������������������������������������������������������������������������������������������������������������������������������������������������

input expression expression� ���������������������������������������������������������������������������������������������������������������������������������������������������������������������

expression termrest_-expression

termrest_-expression

� ���������������������������������������������������������������������������������������������������������������������������������������������������������������������

term IDENTIFIER parenthesized_-expression

� ���������������������������������������������������������������������������������������������������������������������������������������������������������������������

parenthesized_-expression

( expression )

� ���������������������������������������������������������������������������������������������������������������������������������������������������������������������

rest_expression +expression

ε ε� ���������������������������������������������������������������������������������������������������������������������������������������������������������������������

���������������

���������������

���������������

���������������

���������������

Figure 2.65 Transition table for an LL(1) parser for the grammar of Figure 2.53.� �����������������������������������������������������������������������������������������������������������

54 SECTION 2.2 From tokens to syntax tree − the syntax

Page 55: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

Prediction stack: expression ’)’ rest_expression EOFPresent input: IDENTIFIER ’+’ IDENTIFIER ’)’ ’+’ IDENTIFIER EOF

Figure 2.66 Prediction stack and present input in a push-down automaton.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

prediction stack

input

. . . . .

kt k+1t

A 0Ai-1A

transition table

A

t

prediction stack

input

i

kt

A 0i-1A

k+1t

A

Figure 2.67 Prediction move in an LL(1) push-down automaton.� �����������������������������������������������������������������������������������������������

SUBSECTION 2.2.4 Creating a top-down parser automatically 55

Page 56: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

prediction stack

input

prediction stack

input

kt

kt

A 0i-1A

k+1t

i-1A A 0

k+1t

Figure 2.68 Match move in an LL(1) push-down automaton.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

IMPORT Input token [1..]; // from lexical analyzer

SET Input token index TO 1;SET Prediction stack TO Empty stack;PUSH Start symbol ON Prediction stack;

WHILE Prediction stack /= Empty stack:Pop top of Prediction stack into Predicted;IF Predicted is a Token class:

// Try a match move:IF Predicted = Input token [Input token index] .class:

SET Input token index TO Input token index + 1; // matchedELSE Predicted /= Input token:

ERROR "Expected token not found: ", Predicted;ELSE Predicted is a Non-terminal:

// Try a prediction move, using the input token as look-ahead:SET Prediction TO

Prediction table [Predicted, Input token [Input token index]];IF Prediction = Empty:

ERROR "Token not expected: ", Input token [Input token index]];ELSE Prediction /= Empty:

PUSH The symbols of Prediction ON Prediction stack;

Figure 2.69 Predictive parsing with an LL(1) push-down automaton.� �����������������������������������������������������������������������������������������������������������

56 SECTION 2.2 From tokens to syntax tree − the syntax

Page 57: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

Initial situation:Prediction stack: inputInput: ’(’ IDENTIFIER ’+’ IDENTIFIER ’)’ ’+’ IDENTIFIER EOF

Prediction moves:Prediction stack: expression EOFPrediction stack: term rest_expression EOFPrediction stack: parenthesized_expression rest_expression EOFPrediction stack: ’(’ expression ’)’ rest_expression EOFInput: ’(’ IDENTIFIER ’+’ IDENTIFIER ’)’ ’+’ IDENTIFIER EOF

Match move on ’(’:Prediction stack: expression ’)’ rest_expression EOFInput: IDENTIFIER ’+’ IDENTIFIER ’)’ ’+’ IDENTIFIER EOF

Figure 2.70 The first few parsing moves for (i+i)+i.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 2.2.4 Creating a top-down parser automatically 57

Page 58: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

// Step 1: construct acceptable set:SET Acceptable set TO Acceptable set of (Prediction stack);

// Step 2: skip unacceptable tokens:WHILE Input token [Input token index] IS NOT IN Acceptable set:

MESSAGE "Token skipped: ", Input token [Input token index];SET Input token index TO Input token index + 1;

// Step 3: resynchronize the parser:SET the flag Resynchronized TO False;WHILE NOT Resynchronized:

Pop top of Prediction stack into Predicted;IF Predicted is a Token class:

// Try a match move:IF Predicted = Input token [Input token index] .class:

SET Input token index TO Input token index + 1; // matchedSET Resynchronized TO True; // resynchronized!

ELSE Predicted /= Input token:Insert a token of class Predicted, including representation;MESSAGE "Token inserted of class ", Predicted;

ELSE Predicted is a Non-terminal:// Do a prediction move:SET Prediction TO

Prediction table [Predicted, Input token [Input token index]];IF Prediction = Empty:

SET Prediction TO Shortest production table [Predicted];// Now Prediction /= Empty:PUSH The symbols of Prediction ON Prediction stack;

Figure 2.71 Acceptable-set error recovery in a predictive parser.� �����������������������������������������������������������������������������������������������������������

58 SECTION 2.2 From tokens to syntax tree − the syntax

Page 59: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

Data definitions:1. A set of pairs of the form (production rule, integer).2a. A set of pairs of the form (non-terminal, integer).2b. A set of pairs of the form (terminal, integer).

Initializations:1a. For each production rule N→A 1 ...An with n>0 there is a pair (N→A 1 ...An ,∞).1b. For each production rule N→ε there is a pair (N→ε, 0).2a. For each non-terminal N there is a pair (N, ∞).2b. For each terminal T there is a pair (T, 1).

Inference rules:1. For each production rule N→A 1 ...An with n>0, if there are pairs (A 1 , l 1) to(An , ln) with all li<∞, the pair (N→A 1 ...An , lN) must be replaced by a pair

(N→A 1 ...An , lnew) where lnew=i=1Σn

li provided lnew<lN .

2. For each non-terminal N, if there are one or more pairs of the form (N→α,li) with li<∞, the pair (N, lN) must be replaced by (N, lnew) where lnew is theminimum of the lis, provided lnew<lN .

Figure 2.72 Closure algorithm for computing lengths of shortest productions.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

Non-terminal Alternative Shortest lengthinput expression EOF 2expression term rest_expression 1term IDENTIFIER 1parenthesized_expression ’(’ expression ’)’ 3rest_expression ε 0

Figure 2.73 Shortest production table for the grammar of Figure 2.53.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 2.2.5 Creating a bottom-up parser automatically 59

Page 60: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

Error detected, since Prediction table [expression, ’+’] is empty:Prediction stack: expression ’)’ rest_expression EOFInput: ’+’ IDENTIFIER ’)’ ’+’ IDENTIFIER EOF

Shortest production for expression:Prediction stack: term rest_expression ’)’ rest_expression EOFInput: ’+’ IDENTIFIER ’)’ ’+’ IDENTIFIER EOF

Shortest production for term:Prediction stack: IDENTIFIER rest_expression ’)’ rest_expression EOFInput: ’+’ IDENTIFIER ’)’ ’+’ IDENTIFIER EOF

Token IDENTIFIER inserted in the input and matched:Prediction stack: rest_expression ’)’ rest_expression EOFInput: ’+’ IDENTIFIER ’)’ ’+’ IDENTIFIER EOF

Normal prediction for rest_expression, resynchronized:Prediction stack: ’+’ expression ’)’ rest_expression EOFInput: ’+’ IDENTIFIER ’)’ ’+’ IDENTIFIER EOF

Figure 2.74 Some steps in parsing (i++i)+i.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

expression(int *e) →term(int *t) {*e = *t;}expression_tail_option(int *e)

;

expression_tail_option(int *e) →’-’ term(int *t) {*e -= *t;}expression_tail_option(int *e)

| ε;

term(int *t) → IDENTIFIER {*t = 1;};

Figure 2.75 Minimal non-left-recursive grammar for expressions.� �����������������������������������������������������������������������������������������������������������

60 SECTION 2.2 From tokens to syntax tree − the syntax

Page 61: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

%lexical get_next_token_class;%token IDENTIFIER;

%start Main_Program, main;

main {int result;}:expression(&result) {printf("result = %d\n", result);}

;

expression(int *e) {int t;}:term(&t) {*e = t;}expression_tail_option(e)

;

expression_tail_option(int *e) {int t;}:’-’ term(&t) {*e -= t;}expression_tail_option(e)

|;

term(int *t):IDENTIFIER {*t = 1;}

;

Figure 2.76 LLgen code for a parser for simple expressions.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 2.2.5 Creating a bottom-up parser automatically 61

Page 62: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

{#include "lex.h"

int main(void) {start_lex(); Main_Program(); return 0;

}

Token_Type Last_Token; /* error recovery support */int Reissue_Last_Token = 0; /* idem */

int get_next_token_class(void) {if (Reissue_Last_Token) {

Token = Last_Token;Reissue_Last_Token = 0;

}else get_next_token();return Token.class;

}

void insert_token(int token_class) {Last_Token = Token; Reissue_Last_Token = 1;Token.class = token_class;/* and set the attributes of Token, if any */

}

void print_token(int token_class) {switch (token_class) {case IDENTIFIER: printf("IDENTIFIER"); break;case EOFILE : printf("<EOF>"); break;default : printf("%c", token_class); break;}

}

#include "../../fg2/LLgen/LLmessage.i"}

Figure 2.77 Auxiliary C code for a parser for simple expressions.� �����������������������������������������������������������������������������������������������������������

62 SECTION 2.2 From tokens to syntax tree − the syntax

Page 63: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

void LLmessage(int class) {switch (class) {default:

insert_token(class);printf("Missing token ");print_token(class);printf(" inserted in front of token ");print_token(LLsymb); printf("\n");break;

case 0:printf("Token deleted: ");print_token(LLsymb); printf("\n");break;

case -1:printf("End of input expected, but found token ");print_token(LLsymb); printf("\n");break;

}}

Figure 2.78 The routine LLmessage() required by LLgen.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

expression(struct expr **ep):{(*ep) = new_expr(); (*ep)->type = ’-’;}expression(&(*ep)->expr) ’-’ term(&(*ep)->term)

| {(*ep) = new_expr(); (*ep)->type = ’T’;}term(&(*ep)->term)

;

term(struct term **tp):{(*tp) = new_term(); (*tp)->type = ’I’;}IDENTIFIER

;

Figure 2.79 Original grammar with code for constructing a parse tree.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 2.2.5 Creating a bottom-up parser automatically 63

Page 64: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

struct expr {int type; /* ’-’ or ’T’ */struct expr *expr; /* for ’-’ */struct term *term; /* for ’-’ and ’T’ */

};#define new_expr() ((struct expr *)malloc(sizeof(struct expr)))

struct term {int type; /* ’I’ only */

};#define new_term() ((struct term *)malloc(sizeof(struct term)))

extern void print_expr(struct expr *e);extern void print_term(struct term *t);

Figure 2.80 Data structures for the parse tree.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

expression(struct expr **ep):expression(ep){ struct expr *e_aux = (*ep);

(*ep) = new_expr(); (*ep)->type = ’-’; (*ep)->expr = e_aux;}’-’ term(&(*ep)->term)

| {(*ep) = new_expr(); (*ep)->type = ’T’;}term(&(*ep)->term)

;

Figure 2.81 Visibly left-recursive grammar with code for constructing a parse tree.� �����������������������������������������������������������������������������������������������������������

64 SECTION 2.2 From tokens to syntax tree − the syntax

Page 65: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

expression(struct expr **ep):{(*ep) = new_expr(); (*ep)->type = ’T’;}term(&(*ep)->term)expression_tail_option(ep)

;

expression_tail_option(struct expr **ep):{ struct expr *e_aux = (*ep);

(*ep) = new_expr(); (*ep)->type = ’-’; (*ep)->expr = e_aux;}’-’ term(&(*ep)->term)expression_tail_option(ep)

|;

Figure 2.82 Adapted LLgen grammar with code for constructing a parse tree.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 2.2.5 Creating a bottom-up parser automatically 65

Page 66: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

(d)

(a)

(c)

(b)

tree

’-’

expr:

*ep:

term:tree

ep:

*ep:

new_expr

e_aux:

ep:

term:

expr:

’-’type:

e_aux:

treetree

ep:

*ep: *ep:

ep:

type:

Figure 2.83 Tree transformation performed by expression_tail_option.� �����������������������������������������������������������������������������������������������

66 SECTION 2.2 From tokens to syntax tree − the syntax

Page 67: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

input → expression EOFexpression → term | expression ’+’ termterm → IDENTIFIER | ’(’ expression ’)’

Figure 2.84 A simple grammar for demonstrating bottom-up parsing.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

Z → E $E → T | E + TT → i | ( E )

Figure 2.85 An abbreviated form of the simple grammar for bottom-up parsing.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

Data definitions:A set S of LR(0) items.

Initializations:S is prefilled externally with one or more LR(0) items.

Inference rules:If S holds an item of the form P→α � Nβ, then for each production rule N→γin G, S must also contain the item N→ � γ.

Figure 2.86 ε closure algorithm for LR(0) item sets for a grammar G.� �����������������������������������������������������������������������������������������������

SUBSECTION 2.2.5 Creating a bottom-up parser automatically 67

Page 68: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

FUNCTION Initial item set RETURNING an item set:SET New item set TO Empty;

// Initial contents - obtain from the start symbol:FOR EACH production rule S→α for the start symbol S:

SET New item set TO New item set + item S→ � α;

RETURN ε closure (New item set);

Figure 2.87 The routine Initial item set for an LR(0) parser.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

FUNCTION Next item set (Item set, Symbol) RETURNING an item set:SET New item set TO Empty;

// Initial contents - obtain from token moves:FOR EACH item N→α � Sβ IN Item set:

IF S = Symbol:SET New item set TO New item set + item N→αS � β;

RETURN ε closure (New item set);

Figure 2.88 The routine Next item set() for an LR(0) parser.� �����������������������������������������������������������������������������������������������������������

68 SECTION 2.2 From tokens to syntax tree − the syntax

Page 69: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

S

S8

3

T

Z -> E·$E -> E·+T

E -> E+·TT -> ·iT -> ·(E)

Z -> E$· T -> (E)·

E -> E+T·

T -> (E·)E -> E·+T

+

E -> T·

S6

S7

T -> ·(E)T -> ·iE -> ·E+TE -> ·TT -> (·E)

T -> i·

T T

(

i i

(

i

0S

)$S9S2

S5

S4

(

S1

+

E E

E -> ·E+TE -> ·TZ -> ·E$

T -> ·iT -> ·(E)

Figure 2.89 Transition diagram for the LR(0) automaton for the grammar of Figure 2.85.� �����������������������������������������������������������������������������������������������

SUBSECTION 2.2.5 Creating a bottom-up parser automatically 69

Page 70: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

|← GOTO table →| ACTION tablesymbol

� �����������������������������������������������������������������

state i + ( ) $ E T

0 5 7 1 6 shift1 3 2 shift2 Z→E$3 5 7 4 shift4 E→E+T5 T→i6 E→T7 5 7 8 6 shift8 3 9 shift9 T→(E)

Figure 2.90 GOTO and ACTION tables for the LR(0) automaton for the grammar of Figure 2.85.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

Stack Input ActionS 0 i + i $ shiftS 0 i S 5 + i $ reduce by T→iS 0 T S 6 + i $ reduce by E→TS 0 E S 1 + i $ shiftS 0 E S 1 + S 3 i $ shiftS 0 E S 1 + S 3 i S 5 $ reduce by T→iS 0 E S 1 + S 3 T S 4 $ reduce by E→E+TS 0 E S 1 $ shiftS 0 E S 1 $ S 2 reduce by Z→E$S 0 Z stop

Figure 2.91 LR(0) parsing of the input i+i.� �����������������������������������������������������������������������������������������������������������

70 SECTION 2.2 From tokens to syntax tree − the syntax

Page 71: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

IMPORT Input token [1..]; // from the lexical analyzer

SET Input token index TO 1;SET Reduction stack TO Empty stack;PUSH Start state ON Reduction stack;

WHILE Reduction stack /= {Start state, Start symbol, End state}SET State TO Top of Reduction stack;SET Action TO Action table [State];IF Action = "shift":

// Do a shift move:SET Shifted token TO Input token [Input token index];SET Input token index TO Input token index + 1; // shiftedPUSH Shifted token ON Reduction stack;SET New state TO Goto table [State, Shifted token .class];PUSH New state ON Reduction stack; // can be Empty

ELSE IF Action = ("reduce", N→α):// Do a reduction move:Pop the symbols of α from Reduction stack;SET State TO Top of Reduction stack; // update StatePUSH N ON Reduction stack;SET New state TO Goto table [State, N];PUSH New state ON Reduction stack; // cannot be Empty

ELSE Action = Empty:ERROR "Error at token ", Input token [Input token index];

Figure 2.92 LR(0) parsing with a push-down automaton.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 2.2.5 Creating a bottom-up parser automatically 71

Page 72: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

look-ahead token� �������������������������������������������������������������������������������������������

state i + ( ) $

0 shift1 shift shift2 Z→E$3 shift shift4 E→E+T E→E+T E→E+T5 T→i T→i T→i6 E→T E→T E→T7 shift shift8 shift shift9 T→(E) T→(E) T→(E)

Figure 2.93 ACTION table for the SLR(1) automaton for the grammar of Figure 2.85.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

stack symbol/look-ahead tokenstate i + ( ) $ E T

0 s5 s1 s61 s3 s22 r13 s5 s7 s44 r3 r3 r35 r4 r4 r46 r2 r2 r27 s5 s7 s8 s68 s3 s99 r5 r5 r5

Figure 2.94 ACTION/GOTO table for the SLR(1) automaton for the grammar of Figure 2.85.� �����������������������������������������������������������������������������������������������������������

72 SECTION 2.2 From tokens to syntax tree − the syntax

Page 73: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

S → A | xbA → aAb | BB → x

Figure 2.95 Grammar for demonstrating the LR(1) technique.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

✔ shift-reduceconflict

1

S->A.{$}

S

B->x.{b$}

S

2

5

7S

a

4S

6S

8S

S0

S

3SS->.A{$}S->.xb{$}A->.aAb{b$}A->.B{b$}B->.x{b$}

A->a.Ab{b$}A->.aAb{b$}A->.B{b$}B->.x{b$}

A

a

B

b

A->aAb.{b$}

A->aA.b{b$}

A->B.{b$}

xB

A x

S->xb.{$}

B->x.{b$}S->x.b{$}

b

Figure 2.96 The SLR(1) automaton for the grammar of Figure 2.95.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 2.2.5 Creating a bottom-up parser automatically 73

Page 74: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

S11

0S

S1

12

S->A.{$}

5

S2 S

10

B->x.{b}

S

S->xb.{$}

S

S->x.b{$}

b

S

b

A->aAb.{$}

A->aA.b{$}

6S

8S

3

7S

A->B.{b}

9S

A->B.{$}

4S

B->x.{$}

S->.A{$}S->.xb{$}A->.aAb{$}A->.B{$}B->.x{$}

A->a.Ab{$}A->.aAb{b}A->.B{b}B->.x{b}

a

A->a.Ab{b}A->.aAb{b}A->.B{b}B->.x{b}

A->aA.b{b}

A->aAb.{b}

A

a a

B B x

Ax

x B

A

b

Figure 2.97 The LR(1) automaton for the grammar of Figure 2.95.� �����������������������������������������������������������������������������������������������������������

74 SECTION 2.2 From tokens to syntax tree − the syntax

Page 75: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

Data definitions:A set S of LR(1) items of the form N→α � β{σ}.

Initializations:S is prefilled externally with one or more LR(1) items.

Inference rules:If S holds an item of the form P→α � Nβ{σ}, then for each production ruleN→γ in G, S must also contain the item N→ � γ{τ}, where τ = FIRST(β{σ}).

Figure 2.98 ε closure algorithm for LR(1) item sets for a grammar G.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

IMPORT Input token [1..]; // from the lexical analyzer

SET Input token index TO 1;SET Reduction stack TO Empty stack;PUSH Start state ON Reduction stack;

WHILE Reduction stack /= {Start state, Start symbol, End state}SET State TO Top of Reduction stack;SET Look ahead TO Input token [Input token index] .class;SET Action TO Action table [State, Look ahead];IF Action = "shift":

// Do a shift move:SET Shifted token TO Input token [Input token index];SET Input token index TO Input token index + 1; // shiftedPUSH Shifted token ON Reduction stack;SET New state TO Goto table [State, Shifted token .class];PUSH New state ON Reduction stack; // cannot be Empty

ELSE IF Action = ("reduce", N→α):// Do a reduction move:Pop the symbols of α from Reduction stack;SET State TO Top of Reduction stack; // update StatePUSH N ON Reduction stack;SET New state TO Goto table [State, N];PUSH New state ON Reduction stack; // cannot be Empty

ELSE Action = Empty:ERROR "Error at token ", Input token [Input token index];

Figure 2.99 LR(1) parsing with a push-down automaton.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 2.2.5 Creating a bottom-up parser automatically 75

Page 76: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

B->x.{$}S->x.b{$}

b

S->xb.{$}

8,12

S6,11

S4,9

a

2 SS

5S

S->A.{$}

1S

S0 3,10S

B->x.{b}

7S

S->.A{$}S->.xb{$}A->.aAb{$}A->.B{$}B->.x{$}

A->a.Ab{b$}A->.aAb{b}A->.B{b}B->.x{b}

A

a

B

Ax

b

A->aAb.{b$}

A->aA.b{b$}

A->B.{b$}

B

x

Figure 2.100 The LALR(1) automaton for the grammar of Figure 2.95.� �����������������������������������������������������������������������������������������������������������

76 CHAPTER 2 From program text to abstract syntax tree

Page 77: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

expression’(’’if’ ’)’ statement

expression’(’’if’ ’)’ statement statement’else’

if_statement

if_statementx > 0

y > 0 p = 0; q = 0;

Figure 2.101 A possible syntax tree for a nested if-statement.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

expression’(’’if’ ’)’ statement

expression’(’’if’ ’)’ statement statement’else’

if_statement

if_statement

x > 0 q = 0;

y > 0 p = 0;

Figure 2.102 An alternative syntax tree for the same nested if-statement.� �����������������������������������������������������������������������������������������������

SECTION 2.3 Conclusion 77

Page 78: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

sw sxsv tx

->N α β. R->R . G H I->R . erroneous_R->G .....

G H

Figure 2.103 LR error recovery − detecting the error.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

sv tx

->N α β. R->R . G H I->R . erroneous_R->G .....

Figure 2.104 LR error recovery − finding an error recovery state.� �����������������������������������������������������������������������������������������������

78 CHAPTER 2 From program text to abstract syntax tree

Page 79: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

sz tx tzsv

-> . ...tytz

β->N α βR .

β -> . ......

. . . . . .R

Figure 2.105 LR error recovery − repairing the stack.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

szsv

-> . ...tytz

β->N α βR .

β -> . ......

tzR

Figure 2.106 LR error recovery − repairing the input.� �����������������������������������������������������������������������������������������������

SECTION 2.3 Conclusion 79

Page 80: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

szsv tz sa

ztβ -> . .........

R

Figure 2.107 LR error recovery − restarting the parser.� �����������������������������������������������������������������������������������������������

80 CHAPTER 2 From program text to abstract syntax tree

Page 81: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

%{#include "tree.h"%}

%union {struct expr *expr;struct term *term;

}

%type <expr> expression;%type <term> term;

%token IDENTIFIER

%start main

%%

main:expression {print_expr($1); printf("\n");}

;

expression:expression ’-’ term{$$ = new_expr(); $$->type = ’-’; $$->expr = $1; $$->term = $3;}

|term{$$ = new_expr(); $$->type = ’T’; $$->term = $1;}

;

term:IDENTIFIER{$$ = new_term(); $$->type = ’I’;}

;

%%

Figure 2.108 Yacc code for constructing parse trees.� �����������������������������������������������������������������������������������������������������������

SECTION 2.3 Conclusion 81

Page 82: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

#include "lex.h"

int main(void) {start_lex();yyparse(); /* routine generated by yacc */return 0;

}

int yylex(void) {get_next_token();return Token.class;

}

intyyerror(const char *msg) {

fprintf(stderr, "%s\n", msg);return 0;

}

Figure 2.109 Auxiliary code for the yacc parser for simple expressions.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

Lexical analysis Syntax analysis���������������������������������������������������������������������������������������������������Top-down Decision on first char-

acter: manual methodDecision on firsttoken: LL(1) method���������������������������������������������������������������������������������������������������

Bottom-up Decision on reduceitems: finite-stateautomata

Decision on reduceitems: LR techniques�

�������

��������

Figure 2.110 A very high-level view of text analysis techniques.� �����������������������������������������������������������������������������������������������

82 CHAPTER 2 From program text to abstract syntax tree

Page 83: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

declaration: decl_specifiers init_declarator? ’;’decl_specifiers: type_specifier decl_specifiers?type_specifier: ’int’ | ’long’init_declarator: declarator initializer?declarator: IDENTIFIER | declarator ’(’ ’)’ | declarator ’[’ ’]’initializer:

’=’ expression| ’=’ ’{’ initializer_list ’}’ | ’=’ ’{’ initializer_list ’,’ ’}’

initializer_list:expression| initializer_list ’,’ initializer_list | ’{’ initializer_list ’}’

Figure 2.111 A simplified grammar for declarations in C.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

type → actual_type | virtual_typeactual_type → actual_basic_type actual_sizevirtual_type → virtual_basic_type virtual_sizeactual_basic_type → ’int’ | ’char’actual_size → ’[’ NUMBER ’]’virtual_basic_type → ’int’ | ’char’ | ’void’virtual_size → ’[’ ’]’

Figure 2.112 Sample grammar for type.� �����������������������������������������������������������������������������������������������������������

SECTION 2.3 Conclusion 83

Page 84: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

3�������������������������������������������������������������������������

Annotating the abstractsyntax tree − the context

84

Page 85: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

Attributeevaluation

rules

B C D

AAInherited attributes of Synthesized attributes of A

inh. synth. inh. synth. inh. synth.

Figure 3.1 Data flow in a node with attributes.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

Constant_definition (INH old symbol table, SYN new symbol table) →’CONST’ Defined_identifier ’=’ Expression ’;’ATTRIBUTE RULES:

SET Expression .symbol table TOConstant_definition .old symbol table;

SET Constant_definition .new symbol table TOUpdated symbol table (

Constant_definition .old symbol table,Defined_identifier .name,Checked type of Constant_definition (Expression .type),Expression .value

);

Defined_identifier (SYN name) → ...

Expression (INH symbol table, SYN type, SYN value) → ...

Figure 3.2 A simple attribute rule for Constant_definition.� �����������������������������������������������������������������������������������������������������������

SECTION 3.1 Attribute grammars 85

Page 86: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

nameDefined_identifier symbol table typeExpression

Constant_definition new symbol tableold symbol table

value

Figure 3.3 Dependency graph of the rule for Constant_definition from Figure 3.1.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

Expression (INH symbol table, SYN type, SYN value) →NumberATTRIBUTE RULES:

SET Expression .type TO Number .type;SET Expression .value TO Number .value;

Figure 3.4 Trivial attribute grammar for Expression.� �����������������������������������������������������������������������������������������������������������

86 SECTION 3.1 Attribute grammars

Page 87: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

nameIdentifier typeNumber value

type=name= value=3.14..

3.14159265"pi"

pi

Expression valuetypesymbol tableDefined_identifier name

real

Sold symbol table=

Constant_definition new symbol table

Figure 3.5 Sample attributed syntax tree with data flow.� �����������������������������������������������������������������������������������������������

SUBSECTION 3.1.2 Attribute evaluation 87

Page 88: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

Sold symbol table= new symbol table=

pi

Identifier

Defined_identifier Expression

Number

3.14159265

name= symbol table= type= value=

value=type=

name="pi"

type=real

value=3.14..

"pi"name=

real 3.14..

real 3.14.."pi" S

S+("pi",real,3.14..)Constant_definition

Figure 3.6 The attributed syntax tree from Figure 3.5 after attribute evaluation.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

Number → Digit_Seq Base_TagDigit_Seq → Digit_Seq Digit | DigitDigit → Digit_Token // 0 1 2 3 4 5 6 7 8 9Base_Tag → ’B’ | ’D’

Figure 3.7 A context-free grammar for octal and decimal numbers.� �����������������������������������������������������������������������������������������������������������

88 SECTION 3.1 Attribute grammars

Page 89: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

Number(SYN value) →Digit_Seq Base_TagATTRIBUTE RULES

SET Digit_Seq .base TO Base_Tag .base;SET Number .value TO Digit_Seq .value;

Digit_Seq(INH base, SYN value) →Digit_Seq[1] DigitATTRIBUTE RULES

SET Digit_Seq[1] .base TO Digit_Seq .base;SET Digit .base TO Digit_Seq .base;SET Digit_Seq .value TO

Digit_Seq[1] .value * Digit_Seq .base + Digit .value;|

DigitATTRIBUTE RULES

SET Digit .base TO Digit_Seq .base;SET Digit_Seq .value TO Digit .value;

Digit(INH base, SYN value) →Digit_TokenATTRIBUTE RULES

SET Digit .value TO Checked digit value (Value_of (Digit_Token .repr [0]) - Value_of (’0’),base

);

Base_Tag(SYN base) →’B’ATTRIBUTE RULES

SET Base_Tag .base TO 8;|

’D’ATTRIBUTE RULES

SET Base_Tag .base TO 10;

Figure 3.8 An attribute grammar for octal and decimal numbers.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 3.1.3 Cycle handling 89

Page 90: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

FUNCTION Checked digit value (Token value, Base) RETURNING an integer:IF Token value < Base: RETURN Token value;ELSE Token value >= Base:

ERROR "Token " Token value " cannot be a digit in base " Base;RETURN Base - 1;

Figure 3.9 The function Checked digit value.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

valuebase Digit_Seq baseBase_Tag

valueNumber

Figure 3.10 The dependency graph of Number.� �����������������������������������������������������������������������������������������������

90 SECTION 3.1 Attribute grammars

Page 91: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

base valueDigit_Seq base

base

Digit

base valueDigit_Seq

value

valueDigit_Seq

base valueDigit

Figure 3.11 The two dependency graphs of Digit_Seq.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

base valueDigit

reprDigit_Token

Figure 3.12 The dependency graph of Digit.� �����������������������������������������������������������������������������������������������

SUBSECTION 3.1.3 Cycle handling 91

Page 92: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

baseBase_TagbaseBase_Tag

’D’’B’

Figure 3.13 The two dependency graphs of Base_Tag.� �����������������������������������������������������������������������������������������������

92 SECTION 3.1 Attribute grammars

Page 93: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

PROCEDURE Evaluate for Digit_Seq alternative_1 (pointer to digit_seq node Digit_Seq,pointer to digit_seq alt_1 node Digit_Seq alt_1

):// Propagate attributes:Propagate for Digit_Seq alternative_1 (Digit_Seq, Digit_Seq alt_1);

// Traverse subtrees:Evaluate for Digit_Seq (Digit_Seq alt_1 .Digit_Seq);Evaluate for Digit (Digit_Seq alt_1 .Digit);

// Propagate attributes:Propagate for Digit_Seq alternative_1 (Digit_Seq, Digit_Seq alt_1);

PROCEDURE Propagate for Digit_Seq alternative_1 (pointer to digit_seq node Digit_Seq,pointer to digit_seq alt_1 node Digit_Seq alt_1

):IF Digit_Seq alt_1 .Digit_Seq .base is not set

AND Digit_Seq .base is set:SET Digit_Seq alt_1 .Digit_Seq .base TO Digit_Seq .base;

IF Digit_Seq alt_1 .Digit .base is not setAND Digit_Seq .base is set:SET Digit_Seq alt_1 .Digit .base TO Digit_Seq .base;

IF Digit_Seq .value is not setAND Digit_Seq alt_1 .Digit_Seq .value is setAND Digit_Seq .base is setAND Digit_Seq alt_1 .Digit .value is set:SET Digit_Seq .value TO

Digit_Seq alt_1 .Digit_Seq .value * Digit_Seq .base+ Digit_Seq alt_1 .Digit .value;

Figure 3.14 Data-flow code for the first alternative of Digit_Seq.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 3.1.5 Multi-visit attribute grammars 93

Page 94: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

PROCEDURE Run the data-flow attribute evaluator on node Number:WHILE Number .value is not set:

PRINT "Evaluate for Number called"; // report progressEvaluate for Number (Number);

// Print one attribute:PRINT "Number .value = ", Number .value;

Figure 3.15 Driver for the data-flow code.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

FUNCTION Topological sort of (a set Set) RETURNING a list:SET List TO Empty list;WHILE there is a Node in Set but not in List:

Append Node and its predecessors to List;RETURN List;

PROCEDURE Append Node and its predecessors to List:// First append the predecessors of Node:FOR EACH Node_1 IN the Set of nodes that Node is dependent on:

IF Node_1 is not in List:Append Node_1 and its predecessors to List;

Append Node to List;

Figure 3.16 Outline code for a simple implementation of topological sort.� �����������������������������������������������������������������������������������������������������������

94 SECTION 3.1 Attribute grammars

Page 95: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

N

Figure 3.17 A fairly long, possibly circular, data-flow path.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

i 2i 1 3 s 2i s 1N

Figure 3.18 An example of an IS-SI graph.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

i 2i 1 N

s 1 s 2i 1 Qs 1i 1 P

2s1s

Figure 3.19 The dependency graph for the production rule N→PQ.� �����������������������������������������������������������������������������������������������

SUBSECTION 3.1.5 Multi-visit attribute grammars 95

Page 96: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

SET the flag Something was changed TO True;

// Initialization step:FOR EACH terminal T IN Attribute grammar:

SET the IS-SI graph of T TO T’s dependency graph;

FOR EACH non-terminal N IN Attribute grammar:SET the IS-SI graph of N TO the empty set;

WHILE Something was changed:SET Something was changed TO False;

FOR EACH production rule P = M 0→M 1 ...Mn IN Attribute grammar:

// Construct the dependency graph copy D:SET the dependency graph D TO a copy of the dependency graph of P;// Add the dependencies already found for Mi i=0...n

:

FOR EACH M IN M 0 ...Mn:FOR EACH dependency d IN the IS-SI graph of M:

Insert d in D;

// Use the dependency graph D:Compute all induced dependencies in D by transitive closure;IF D contains a cycle: ERROR "Cycle found in production", P// Propagate the newly discovered dependencies:FOR EACH M IN M 0 ...Mn:

FOR EACH dependency d IN DSUCH THAT the attributes in d are attributes of M:IF there is no dependency d in the IS-SI graph of M:

Enter a dependency d into the IS-SI graph of M;SET Something was changed TO True;

Figure 3.20 Outline of the strong-cyclicity test for an attribute grammar.� �����������������������������������������������������������������������������������������������������������

96 SECTION 3.1 Attribute grammars

Page 97: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

i 2i 1 N

s 1 s 2i 1 Qs 1i 1 P

2s1s

Figure 3.21 The IS-SI graphs of N, P, and Q collected so far.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

N

s 1 s 2i 1 Qs 1i 1 P

1i 2i 2s1s

Figure 3.22 Transitive closure over the dependencies of N, P, Q and D.� �����������������������������������������������������������������������������������������������

SUBSECTION 3.1.9 Equivalence of L-attributed and S-attributed grammars 97

Page 98: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

2i 1 N

s 1 s 2i 1 Qs 1i 1 P

i 2s1s

Figure 3.23 The new IS-SI graphs of N, P, and Q.� �����������������������������������������������������������������������������������������������

98 SECTION 3.1 Attribute grammars

Page 99: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

// Visit 1 from the parent: flow of control from parent enters here.// The parent has set some inherited attributes, the set IN 1.

// Visit some children Mk, Ml, ...:

Compute some inherited attributes of Mk, the set (IMk)1;Visit Mk for the first time;// Mk returns with some of its synthesized attributes evaluated.

Compute some inherited attributes of Ml, the set (IMl)1;Visit Ml for the first time;// Ml returns with some of its synthesized attributes evaluated.

... // Perhaps visit some more children, including possibly Mk or// Ml again, while supplying the proper inherited attributes// and obtaining synthesized attributes in return.

// End of the visits to children.

Compute some of N’s synthesized attributes, the set SN 1;Leave to the parent;

// End of visit 1 from the parent.

// Visit 2 from the parent: flow of control re-enters here.// The parent has set some inherited attributes, the set IN 2.

... // Again visit some children while supplying inherited// attributes and obtaining synthesized attributes in return.

Compute some of N’s synthesized attributes, the set SN 2;Leave to the parent;

// End of visit 2 from the parent.

... // Perhaps code for some more visits 3..n from the parent,// supplying sets IN 3 to INn and yielding// sets SN 3 to SNn.

Figure 3.24 Outline code for multi-visit attribute evaluation.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 3.1.11 Conclusion 99

Page 100: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

9

5

4

11

10

7

8

6

3

performs -th visit toh Mk

2

yielding

1

providing

performs -th visit toj M l

yielding

providing

-th visit toi N

provides

yields

(SM )

l(IM )

i

(SM )

SNi

IN

IN

(IM )

l

iSN

i

jl

kj

j

h(IM )

N

. . . . . .. . .Mk

Ml

k

h

hk(SM )hk(IM )

jl(SM )

Figure 3.25 The i-th visit to a node N, visiting two children, Mk and Ml .� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

PROCEDURE Visit_i to N (pointer to an N node Node):SELECT Node .type:

CASE alternative_1:Visit_i to N alternative_1 (Node);

...CASE alternative_k:

Visit_i to N alternative_k (Node);...

Figure 3.26 Structure of an i-th visit routine for N.� �����������������������������������������������������������������������������������������������������������

100 SECTION 3.1 Attribute grammars

Page 101: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

base Digit_Seq

valuebase

baseBase_Tag

valueNumber

value

Digit

Figure 3.27 The IS-SI graphs of the non-terminals from grammar 3.8.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

IN 1 SN 1

Number valueDigit_Seq base valueDigit base valueBase_Tag base

Figure 3.28 Partitionings of the attributes of grammar 3.8.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 3.2.1 Threading the AST 101

Page 102: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

PROCEDURE Visit_1 to Number alternative_1 (pointer to number node Number,pointer to number alt_1 node Number alt_1

):// Visit 1 from the parent: flow of control from the parent enters here.// The parent has set the attributes in IN 1 of Number, the set {}.

// Visit some children:

// Compute the attributes in IN 1 of Base_Tag (), the set {}:// Visit Base_Tag for the first time:Visit_1 to Base_Tag (Number alt_1 .Base_Tag);// Base_Tag returns with its SN 1, the set { base }, evaluated.

// Compute the attributes in IN 1 of Digit_Seq (), the set { base }:SET Number alt_1 .Digit_Seq .base TO Number alt_1 .Base_Tag .base;// Visit Digit_Seq for the first time:Visit_1 to Digit_Seq (Number alt_1 .Digit_Seq);// Digit_Seq returns with its SN 1, the set { value }, evaluated.

// End of the visits to children.

// Compute the attributes in SN 1 of Number, the set { value }:SET Number .value TO Number alt_1 .Digit_Seq .value;

Figure 3.29 Visiting code for Number nodes.� �����������������������������������������������������������������������������������������������������������

102 SECTION 3.2 Manual methods

Page 103: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

PROCEDURE Visit_1 to Digit_Seq alternative_1 (pointer to digit_seq node Digit_Seq,pointer to digit_seq alt_1 node Digit_Seq alt_1

):// Visit 1 from the parent: flow of control from the parent enters here.// The parent has set the attributes in IN 1 of Digit_Seq, the set { base }.

// Visit some children:

// Compute the attributes in IN 1 of Digit_Seq (), the set { base }:SET Digit_Seq alt_1 .Digit_Seq .base TO Digit_Seq .base;// Visit Digit_Seq for the first time:Visit_1 to Digit_Seq (Digit_Seq alt_1 .Digit_Seq);// Digit_Seq returns with its SN 1, the set { value }, evaluated.

// Compute the attributes in IN 1 of Digit (), the set { base }:SET Digit_Seq alt_1 .Digit .base TO Digit_Seq .base;// Visit Digit for the first time:Visit_1 to Digit (Digit_Seq alt_1 .Digit);// Digit returns with its SN 1, the set { value }, evaluated.

// End of the visits to children.

// Compute the attributes in SN 1 of Digit_Seq, the set { value }:SET Digit_Seq .value TO

Digit_Seq alt_1 .Digit_Seq .value * Digit_Seq .base +Digit_Seq alt_1 .Digit .value;

Figure 3.30 Visiting code for Digit_Seq alternative_1 nodes.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

B1 BB2 3

C C C2 3

4B

1

A

Figure 3.31 Data flow in part of a parse tree for an L-attributed grammar.� �����������������������������������������������������������������������������������������������

SUBSECTION 3.2.1 Threading the AST 103

Page 104: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

{#include "symbol_table.h"}

%lexical get_next_token_class;%token IDENTIFIER;%token DIGIT;

%start Main_Program, main;

main {symbol_table sym_tab; int result;}:{init_symbol_table(&sym_tab);}declarations(sym_tab)expression(sym_tab, &result){printf("result = %d\n", result);}

;

declarations(symbol_table sym_tab):declaration(sym_tab) [ ’,’ declaration(sym_tab) ]* ’;’

;

declaration(symbol_table sym_tab) {symbol_entry *sym_ent;}:IDENTIFIER {sym_ent = look_up(sym_tab, Token.repr);}’=’ DIGIT {sym_ent->value = Token.repr - ’0’;}

;

expression(symbol_table sym_tab; int *e) {int t;}:term(sym_tab, &t) {*e = t;}expression_tail_option(sym_tab, e)

;

expression_tail_option(symbol_table sym_tab; int *e) {int t;}:’-’ term(sym_tab, &t) {*e -= t;}expression_tail_option(sym_tab, e)

|;

term(symbol_table sym_tab; int *t):IDENTIFIER {*t = look_up(sym_tab, Token.repr)->value;}

;

Figure 3.32 LLgen code for an L-attributed grammar for simple expressions.� �����������������������������������������������������������������������������������������������������������

104 SECTION 3.2 Manual methods

Page 105: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

Declaration →Type_Declarator(type) Declared_Idf_Sequence(type) ’;’

;

Declared_Idf_Sequence(INH type) →Declared_Idf(type)

|Declared_Idf_Sequence(type) ’,’ Declared_Idf(type)

;

Declared_Idf(INH type) →Idf(repr)ATTRIBUTE RULES:

Add to symbol table (repr, type);;

Figure 3.33 Sketch of an L-attributed grammar for Declaration.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

Declaration →Type_Declarator(type) Declared_Idf_Sequence(repr list) ’;’ATTRIBUTE RULES:

FOR EACH repr IN repr list:Add to symbol table(repr, type);

Declared_Idf_Sequence(SYN repr list) →Declared_Idf(repr)ATTRIBUTE RULES:

SET repr list TO Convert to list (repr);|

Declared_Idf_Sequence(old repr list) ’,’ Declared_Idf(repr)ATTRIBUTE RULES:

SET repr list TO Append to list (old repr list, repr);;

Declared_Idf(SYN repr) →Idf(repr)

;

Figure 3.34 Sketch of an S-attributed grammar for Declaration.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 3.2.2 Symbolic interpretation 105

Page 106: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

L-attributed S-attributedOrdered

Figure 3.35 Pictorial comparison of three types of attribute grammars.� �����������������������������������������������������������������������������������������������

106 SECTION 3.2 Manual methods

Page 107: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

Last node pointer

*

bb

*

4 *

ca

-

Last node pointer

*

bb

*

4 *

ca

-

X

X

final situation

initial situation

Figure 3.36 Control flow graph for the expression b*b - 4*a*c.� �����������������������������������������������������������������������������������������������

SUBSECTION 3.2.2 Symbolic interpretation 107

Page 108: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

#include "parser.h" /* for types AST_node and Expression */#include "thread.h" /* for self check */

/* PRIVATE */static AST_node *Last_node;

static void Thread_expression(Expression *expr) {switch (expr->type) {case ’D’:

Last_node->successor = expr; Last_node = expr;break;

case ’P’:Thread_expression(expr->left);Thread_expression(expr->right);Last_node->successor = expr; Last_node = expr;break;

}}

/* PUBLIC */AST_node *Thread_start;

void Thread_AST(AST_node *icode) {AST_node Dummy_node;

Last_node = &Dummy_node; Thread_expression(icode);Last_node->successor = (AST_node *)0;Thread_start = Dummy_node.successor;

}

Figure 3.37 Threading code for the demo compiler from Section 1.2.� �����������������������������������������������������������������������������������������������������������

108 SECTION 3.2 Manual methods

Page 109: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

PROCEDURE Thread if statement (If node pointer):Thread expression (If node pointer .condition);SET Last node pointer .successor TO If node pointer;

SET End if join node TO Generate join node ();

SET Last node pointer TO address of a local node Aux last node;Thread block (If node pointer .then part);SET If node pointer .true successor TO Aux last node .successor;SET Last node pointer .successor TO address of End if join node;

SET Last node pointer TO address of Aux last node;Thread block (If node pointer .else part);SET If node pointer .false successor TO Aux last node .successor;SET Last node pointer .successor TO address of End if join node;

SET Last node pointer TO address of End if join node;

Figure 3.38 Sample threading routine for if-statements.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

Then_part Else_partCondition

If_statement

X

Last node pointer

Figure 3.39 AST of an if-statement before threading.� �����������������������������������������������������������������������������������������������

SUBSECTION 3.2.3 Data-flow equations 109

Page 110: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

Then_part Else_partCondition

If_statement

X

Last node pointer

End_if

Figure 3.40 AST and control flow graph of an if-statement after threading.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

If_statement(INH successor, SYN first) →’IF’ Condition ’THEN’ Then_part ’ELSE’ Else_part ’END’ ’IF’ATTRIBUTE RULES:

SET If_statement .first TO Condition .first;SET Condition .true successor TO Then_part .first;SET Condition .false successor TO Else_part .first;SET Then_part .successor TO If_statement .successor;SET Else_part .successor TO If_statement .successor;

Figure 3.41 Threading an if-statement using attribute rules.� �����������������������������������������������������������������������������������������������������������

110 SECTION 3.2 Manual methods

Page 111: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

Then_part Else_partCondition

If_statement

X

Last node pointer

End_if

Figure 3.42 AST and doubly-linked control flow graph of an if-statement.� �����������������������������������������������������������������������������������������������

SUBSECTION 3.2.3 Data-flow equations 111

Page 112: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

If_statement

Condition

>

0y

Then_part

End_if

Else_part

5y5y

5

y 5

50

5y

15y

5y

5y

5y

5y

xx

x

x

x

x x

x

x

Figure 3.43 Stack representations in the control flow graph of an if-statement.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

FUNCTION Symbolically interpret an if statement (Stack representation, If node

) RETURNING a stack representation:SET New stack representation TO

Symbolically interpret a condition (Stack representation, If node .condition

);Discard top entry from New stack representation;RETURN Merge stack representations (

Symbolically interpret a statement sequence (New stack representation, If node .then part

),Symbolically interpret a statement sequence (

New stack representation, If node .else part)

);

Figure 3.44 Outline of a routine Symbolically interpret an if statement.� �����������������������������������������������������������������������������������������������������������

112 SECTION 3.2 Manual methods

Page 113: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

v

Ffrom

v

FTto

from

v

v E

FTto

from

v ?

v E’

FfromTto

v E

FTto

from

For_statement

Body

End_for

=: v

v

FTto

from

E

From_expr To_expr expr

Figure 3.45 Stack representations in the control flow graph of a for-statement.� �����������������������������������������������������������������������������������������������

SUBSECTION 3.2.5 Carrying the information upstream − live analysis 113

Page 114: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

int i = 0;

while (some condition) {if (i > 0) printf("Loop reentered: i = %d\n", i);i++;

}

Figure 3.46 Value set analysis in the presence of a loop statement.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

Data definitions:Stack representations, with entries for every item we are interested in.

Initializations:1. Empty stack representations are attached to all arrows in the control flowgraph residing in the threaded AST.2. Some stack representations at strategic points are initialized in accordancewith properties of the source language; for example, the stack representationsof input parameters are initialized to Initialized.

Inference rules:For each node type, source language dependent rules allow inferences to bemade, adding information to the stack representation on the outgoing arrowsbased on those on the incoming arrows and the node itself, and vice versa.

Figure 3.47 Full symbolic interpretation as a closure algorithm.� �����������������������������������������������������������������������������������������������

114 SECTION 3.2 Manual methods

Page 115: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

x := y + 3

:=

x +

3y

(a) (b)

Figure 3.48 An assignment as a full control flow graph and as a single node.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

IN(N) =M=dynamic predecessor of N

∪ OUT (M)

OUT (N) = (IN(N) \ KILL(N)) ∪ GEN (N)

Figure 3.49 Data-flow equations for a node N.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 3.2.5 Carrying the information upstream − live analysis 115

Page 116: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

first node

return

return

exit node KILL = all local information

IN := all value parameters have values

Figure 3.50 Data-flow details at routine entry and exit.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

Data definitions:1. Constant KILL and GEN sets for each node.2. Variable IN and OUT sets for each node.

Initializations:1. The IN set of the top node is initialized with information established exter-nally.2. For all other nodes N, IN(N) and OUT (N) are set to empty.

Inference rules:1. For any node N, IN(N) should contain

M=dynamic predecessor of N∪ OUT (M).

2. For any node N, OUT (N) should contain

(IN(N) \ KILL(N)) ∪ GEN (N).

Figure 3.51 Closure algorithm for solving the data-flow equations.� �����������������������������������������������������������������������������������������������

116 SECTION 3.2 Manual methods

Page 117: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

may be initializedy

may be uninitializedy

may be initializedx

may be uninitializedx

Figure 3.52 Bit patterns for properties of the variables x and y.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

0 1 1 1 is guaranteed to have a valuex

y may or may not have a value

is guaranteed not to have a valuex0001

the combination 00 for is an errory

Figure 3.53 Examples of bit patterns for properties of the variables x and y.� �����������������������������������������������������������������������������������������������

SECTION 3.3 Conclusion 117

Page 118: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

x := y y := 0

1 0 0 1

0 0 0 1

0 01 0

0 10 1

0 001

1 0 0 1

1 0 0 1

0 0 0 1

1 0 0 1

0 1 00

0 10 1

1 0 0 1

1 1 0 1

1 0 0 1

y > 0

KILL

\\

KILL

end_if

GEN GEN

Figure 3.54 Data-flow propagation through an if-statement.� �����������������������������������������������������������������������������������������������

118 CHAPTER 3 Annotating the abstract syntax tree − the context

Page 119: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

{ int x;x = ...; /* code fragment 1, does not use x */if (...) {

... /* code fragment 2, does not use x */print(x); /* code fragment 3, uses x */... /* code fragment 4, does not use x */

} else {int y;... /* code fragment 5, does not use x,y */print(x); /* code fragment 6, uses x, but not y */... /* code fragment 7, does not use x,y */y = ...; /* code fragment 8, does not use x,y */... /* code fragment 9, does not use x,y */print(y); /* code fragment 10, uses y but not x */... /* code fragment 11, does not use x,y */

}x = ...; /* code fragment 12, does not use x */... /* code fragment 13, does not use x */print(x); /* code fragment 14, uses x */... /* code fragment 15, does not use x */

}

Figure 3.55 A segment of C code to demonstrate live analysis.� �����������������������������������������������������������������������������������������������������������

SECTION 3.3 Conclusion 119

Page 120: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

x = ...; (1)

...

...; (2)

print(x); (3)

...; (4)

LU_x = true

BPLU_x ={}

BPLU_x ={1}

Figure 3.56 The first few steps in live analysis for Figure 3.55 using backpatch lists.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

x = ...; (1)

...

...; (2)

print(x); (3)

...; (4)

LU_x = false

LU_x = trueBPLU_x =

{3}

Figure 3.57 Live analysis for Figure 3.55, after a few steps.� �����������������������������������������������������������������������������������������������

120 CHAPTER 3 Annotating the abstract syntax tree − the context

Page 121: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

x = ...; (1)

...

LU_x = false

LU_x = true LU_x = true

...; (5)

print(x); (6)

...; (7)

y = ...; (8)

...; (9)

print(y);(10)

...; (11)

...; (4)

...; (2)

LU_y = true

LU_y = false

print(x); (3)

end_if

x = ...; (12)

BPLU_x =

BPLU_x ={3}

{6}

BPLU_y ={10}

BPLU_x ={3, 6}

Figure 3.58 Live analysis for Figure 3.55, merging at the end-if node.� �����������������������������������������������������������������������������������������������

SECTION 3.3 Conclusion 121

Page 122: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

OUT (N) =M=dynamic successor of N

∪ IN(M)

IN(N) = (OUT (N) \ KILL(N)) ∪ GEN (N)

Figure 3.59 Backwards data-flow equations for a node N.� �����������������������������������������������������������������������������������������������������������

122 CHAPTER 3 Annotating the abstract syntax tree − the context

Page 123: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

x = ...; (1)

...

...; (5)

print(x); (6)

...; (7)

y = ...; (8)

...; (9)

print(y);(10)

...; (11)

...; (4)

...; (2)

print(x); (3)

end_if

x = ...; (12)

...; (13)

...; (15)

print(x);(14)

00

00

00

00

00

00

00

00

10

10

00

01

00

01

10

10

10

10

10

Figure 3.60 Live analysis for Figure 3.55 using backward data-flow equations.� �����������������������������������������������������������������������������������������������

SECTION 3.3 Conclusion 123

Page 124: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

S(SYN s) →A(i1, s1)ATTRIBUTE RULES:

SET i1 TO s1;SET s TO s1;

A(INH i1, SYN s1) →A(i2, s2) ’a’ATTRIBUTE RULES:

SET i2 TO i1;SET s1 TO s2;

|B(i2, s2)ATTRIBUTE RULES:

SET i2 TO i1;SET s1 TO s2;

B(INH i, SYN s) →’b’ATTRIBUTE RULES: SET s TO i;

Figure 3.61 Attribute grammar for Exercise {#ShowCycle}.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

i ss iT U

Figure 3.62 IS-SI graphs for T and U.� �����������������������������������������������������������������������������������������������

124 CHAPTER 3 Annotating the abstract syntax tree − the context

Page 125: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

x = ...; (1)

y := 1; (2)

print(x); (4)

z := x*x - y*y; (3)

y := y+1; (5)

y>100 (6)

Figure 3.63 Example program for a very busy expression.� �����������������������������������������������������������������������������������������������

SECTION 3.3 Conclusion 125

Page 126: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

4�������������������������������������������������������������������������

Processing theintermediate code

126

Page 127: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

systemdesign

Largely language- and paradigm-independent

Machinegeneration

independentand paradigm-

Run-time

Language- andparadigm-dependent

Largely machine-

Syntaxanalysis

Interpretation

Lexicalanalysis handling

Contextcode

Intermediate

codegeneration

Figure 4.1 The status of the various modules in compiler construction.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

4.0

3.0re:

im:

Figure 4.2 A value of type Complex_Number as the programmer sees it.� �����������������������������������������������������������������������������������������������

SECTION 4.2 Code generation 127

Page 128: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

name:

type:

next:

name:

type:

next:

"re"

"im"

V

V

type:

value: 3.0

type:

value: 4.0

Vvalue:

name:

class:

field:

name:

class:

type number:

RECORD

BASIC

3

"real"

2

values:

size:

type:

Specific to the given value of typecomplex_number

"complex_number"

Common to all values of typecomplex_number

Figure 4.3 A representation of the value of Figure 4.2 in a recursive interpreter.� �����������������������������������������������������������������������������������������������

128 SECTION 4.2 Code generation

Page 129: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

PROCEDURE Elaborate if statement (If node):SET Result TO Evaluate condition (If node .condition);IF Status .mode /= Normal mode: RETURN;IF Result .type /= Boolean:

ERROR "Condition in if-statement is not of type Boolean";RETURN;

IF Result .boolean .value = True:Elaborate statement (If node .then part);

ELSE Result .boolean .value = False:// Check if there is an else-part at all:IF If node .else part /= No node:

Elaborate statement (If node .else part);ELSE If node .else part = No node:

SET Status .mode TO Normal mode;

Figure 4.4 Outline of a routine for recursively interpreting an if-statement.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

WHILE Active node .type /= End of program type:SELECT Active node .type:

CASE ...CASE If type:

// We arrive here after the condition has been evaluated;// the Boolean result is on the working stack.SET Value TO Pop working stack ();IF Value .boolean .value = True:

SET Active node TO Active node .true successor;ELSE Value .boolean .value = False:

IF Active node .false successor /= No node:SET Active node TO Active node .false successor;

ELSE Active node .false successor = No node:SET Active node TO Active node .successor;

CASE ...

Figure 4.5 Sketch of the main loop of an iterative interpreter, showing the code for an if-statement.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 4.2.3 Trivial code generation 129

Page 130: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

#include "parser.h" /* for types AST_node and Expression */#include "thread.h" /* for Thread_AST() and Thread_start */#include "stack.h" /* for Push() and Pop() */#include "backend.h" /* for self check */

/* PRIVATE */static AST_node *Active_node_pointer;

static void Interpret_iteratively(void) {while (Active_node_pointer != 0) {

/* there is only one node type, Expression: */Expression *expr = Active_node_pointer;switch (expr->type) {case ’D’:

Push(expr->value);break;

case ’P’: {int e_left = Pop(); int e_right = Pop();switch (expr->oper) {case ’+’: Push(e_left + e_right); break;case ’*’: Push(e_left * e_right); break;}}break;

}Active_node_pointer = Active_node_pointer->successor;

}printf("%d\n", Pop()); /* print the result */

}/* PUBLIC */

void Process(AST_node *icode) {Thread_AST(icode); Active_node_pointer = Thread_start;Interpret_iteratively();

}

Figure 4.6 An iterative interpreter for the demo compiler of Section 1.2.� �����������������������������������������������������������������������������������������������������������

130 SECTION 4.2 Code generation

Page 131: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

condition

statement 1 statement 2

statement 3

statement 4

IF

IFEND

Figure 4.7 An AST stored as a graph.� �����������������������������������������������������������������������������������������������

SUBSECTION 4.2.3 Trivial code generation 131

Page 132: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

condition

statement 1

statement 2

statement 3

statement 4

condition

statement 1

statement 2

statement 3

statement 4

IF_FALSE

JUMP

IF

(a)

(b)

Figure 4.8 Storing the AST in an array (a) and as pseudo-instructions (b).� �����������������������������������������������������������������������������������������������

132 SECTION 4.2 Code generation

Page 133: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

:=

a +

9*

2[

+

* d

c4

b

+

9*

2mem

*

4

@b +

+

Rc

Rd

Ra

and Register Allocation

Intermediate Code Generation

Figure 4.9 Two ASTs for the expression a := (b[4*c + d] * 2) + 9.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

R

mem

+

+M

*

R c

R

i

o

d

+

M

Rd

*

CRi

Load_Byte (M+R )[R ],C,RLoad_Address M[R ],C,Ri d dio

Figure 4.10 Two sample instructions with their ASTs.� �����������������������������������������������������������������������������������������������

SUBSECTION 4.2.3 Trivial code generation 133

Page 134: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

pre-IC

processing generation

Executablecode

output

Inter-

codepost-processing

Target code Machine

mediate

propergeneration

code

Code

exe

Executablecode

Figure 4.11 Overall structure of a code generator.� �����������������������������������������������������������������������������������������������

134 SECTION 4.2 Code generation

Page 135: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

#include "parser.h" /* for types AST_node and Expression */#include "thread.h" /* for Thread_AST() and Thread_start */#include "backend.h" /* for self check */

/* PRIVATE */static AST_node *Active_node_pointer;

static void Trivial_code_generation(void) {printf("#include \"stack.h\"\nint main(void) {\n");while (Active_node_pointer != 0) {

/* there is only one node type, Expression: */Expression *expr = Active_node_pointer;switch (expr->type) {case ’D’:

printf("Push(%d);\n", expr->value);break;

case ’P’:printf("{\n\

int e_left = Pop(); int e_right = Pop();\n\switch (%d) {\n\case ’+’: Push(e_left + e_right); break;\n\case ’*’: Push(e_left * e_right); break;\n\}}\n",expr->oper

);break;

}Active_node_pointer = Active_node_pointer->successor;

}printf("printf(\"%%d\\n\", Pop()); /* print the result */\n");printf("return 0;}\n");

}/* PUBLIC */

void Process(AST_node *icode) {Thread_AST(icode); Active_node_pointer = Thread_start;Trivial_code_generation();

}

Figure 4.12 A trivial code generator for the demo compiler of Section 1.2.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 4.2.4 Simple code generation 135

Page 136: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

#include "stack.h"int main(void) {Push(7);Push(1);Push(5);{

int e_left = Pop(); int e_right = Pop();switch (43) {case ’+’: Push(e_left + e_right); break;case ’*’: Push(e_left * e_right); break;}}

{int e_left = Pop(); int e_right = Pop();switch (42) {case ’+’: Push(e_left + e_right); break;case ’*’: Push(e_left * e_right); break;}}

printf("%d\n", Pop()); /* print the result */return 0;}

Figure 4.13 Code for (7*(1+5)) generated by the code generator of Figure 4.12.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

int main(void) {Expression_D(7);Expression_D(1);Expression_D(5);Expression_P(43); /* 43 = ASCII value of ’+’ */Expression_P(42); /* 42 = ASCII value of ’*’ */Print();return 0;

}

Figure 4.14 Possible threaded code for (7*(1+5)).� �����������������������������������������������������������������������������������������������������������

136 SECTION 4.2 Code generation

Page 137: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

#include "stack.h"

void Expression_D(int digit) {Push(digit);

}

void Expression_P(int oper) {int e_left = Pop(); int e_right = Pop();switch (oper) {case ’+’: Push(e_left + e_right); break;case ’*’: Push(e_left * e_right); break;}

}

void Print(void) {printf("%d\n", Pop());

}

Figure 4.15 Routines for the threaded code for (7*(1+5)).� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

case ’P’:printf("{\n\

int e_left = Pop(); int e_right = Pop();\n");switch (expr->oper) {case ’+’: printf("Push(e_left + e_right);\n"); break;case ’*’: printf("Push(e_left * e_right);\n"); break;}printf("}\n");break;

Figure 4.16 Partial evaluation in a segment of the code generator.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 4.2.4 Simple code generation 137

Page 138: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

#include "stack.h"int main(void) {Push(7);Push(1);Push(5);{int e_left = Pop(); int e_right = Pop(); Push(e_left + e_right);}{int e_left = Pop(); int e_right = Pop(); Push(e_left * e_right);}printf("%d\n", Pop()); /* print the result */return 0;}

Figure 4.17 Code for (7*(1+5)) generated by the code generator of Figure 4.16.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

case ’P’:printf("{\n\

int e_left = Pop(); int e_right = Pop();\n");switch (expr->oper) {case ’+’: printf("Push(e_left + e_right);\n"); break;case ’*’: printf("Push(e_left * e_right);\n"); break;}printf("}\n");break;

Figure 4.18 Foreground (run-now) view of partially evaluating code.� �����������������������������������������������������������������������������������������������������������

138 SECTION 4.2 Code generation

Page 139: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

case ’P’:printf("{\n\

int e_left = Pop(); int e_right = Pop();\n");switch (expr->oper) {case ’+’: printf("Push(e_left + e_right);\n"); break;case ’*’: printf("Push(e_left * e_right);\n"); break;}printf("}\n");break;

Figure 4.19 Background (run-later) view of partially evaluating code.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

stack

BP

SP

dire

ctio

n of

gro

wth

Figure 4.20 Data administration in a simple stack machine.� �����������������������������������������������������������������������������������������������

SUBSECTION 4.2.4 Simple code generation 139

Page 140: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

Instruction Actions

Push_Const c SP:=SP+1; stack[SP]:=c;Push_Local i SP:=SP+1; stack[SP]:=stack[BP+i];Store_Local i stack[BP+i]:=stack[SP]; SP:=SP-1;

Add_Top2 stack[SP-1]:=stack[SP-1]+stack[SP]; SP:=SP-1;Subtr_Top2 stack[SP-1]:=stack[SP-1]-stack[SP]; SP:=SP-1;Mult_Top2 stack[SP-1]:=stack[SP-1]*stack[SP]; SP:=SP-1;

Figure 4.21 Stack machine instructions.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

Instruction Actions

Load_Const c,Rn Rn:=c;Load_Mem x,Rn Rn:=x;Store_Reg Rn,x x:=Rn;

Add_Reg Rm,Rn Rn:=Rn+Rm;Subtr_Reg Rm,Rn Rn:=Rn-Rm;Mult_Reg Rm,Rn Rn:=Rn*Rm;

Figure 4.22 Register machine instructions.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

-

* *

bb 4 *

a c

Figure 4.23 The abstract syntax tree for b*b - 4*(a*c).� �����������������������������������������������������������������������������������������������

140 SECTION 4.2 Code generation

Page 141: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

Mult_Top2: Store_Local i:

-

i

Add_Top2:

Push_Local i:

:=

c

+

*

Push_Const c:

Subtr_Top2:

i

Figure 4.24 The abstract syntax trees for the stack machine instructions.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

Push_Local #bPush_Local #b Mult_Top2Push_Const 4

Push_Local #cPush_Local #a

Mult_Top2Mult_Top2

Subtr_Top2

Figure 4.25 The abstract syntax tree for b*b - 4*(a*c) rewritten.� �����������������������������������������������������������������������������������������������

SUBSECTION 4.2.4 Simple code generation 141

Page 142: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

PROCEDURE Generate code (Node):SELECT Node .type:

CASE Constant type: Emit ("Push_Const" Node .value);CASE LocalVar type: Emit ("Push_Local" Node .number);CASE StoreLocal type: Emit ("Store_Local" Node .number);CASE Add type:

Generate code (Node .left); Generate code (Node .right);Emit ("Add_Top2");

CASE Subtract type:Generate code (Node .left); Generate code (Node .right);Emit ("Subtr_Top2");

CASE Multiply type:Generate code (Node .left); Generate code (Node .right);Emit ("Mult_Top2");

Figure 4.26 Depth-first code generation for a stack machine.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

b b

b

b*b b*b

4

a

4

b*b

b*b-4*(a*c)

b*b

4

a

c

(a*c)

4

b*b b*b

4*(a*c)

(1) (2) (3) (4)

(8)(7)(6)(5)

(9)

Figure 4.27 Successive stack configurations for b*b - 4*(a*c).� �����������������������������������������������������������������������������������������������

142 SECTION 4.2 Code generation

Page 143: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

Add_Reg R ,R :m n Subtr_Reg R ,R :m n

Rn

Rn

Rn

x

Mult_Reg R ,R :m n Store_Reg R ,x:n

R

R

R

+

n

n

m

R

*

R

n

m

R

R

-

m

n

R

x

n

:=

Rn

c

c Load_Mem ,R :nLoad_Const ,R :n x

Figure 4.28 The abstract syntax trees for the register machine instructions.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

PROCEDURE Generate code (Node, a register Target, a register set Aux):SELECT Node .type:

CASE Constant type:Emit ("Load_Const " Node .value ",R" Target);

CASE Variable type:Emit ("Load_Mem " Node .address ",R" Target);

CASE ...CASE Add type:

Generate code (Node .left, Target, Aux);SET Target 2 TO An arbitrary element of Aux;SET Aux 2 TO Aux \ Target 2;

// the \ denotes the set difference operationGenerate code (Node .right, Target 2, Aux 2);Emit ("Add_Reg R" Target 2 ",R" Target);

CASE ...

Figure 4.29 Simple code generation with register allocation.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 4.2.4 Simple code generation 143

Page 144: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

PROCEDURE Generate code (Node, a register number Target):SELECT Node .type:

CASE Constant type:Emit ("Load_Const " Node .value ",R" Target);

CASE Variable type:Emit ("Load_Mem " Node .address ",R" Target);

CASE ...CASE Add type:

Generate code (Node .left, Target);Generate code (Node .right, Target+1);Emit ("Add_Reg R" Target+1 ",R" Target);

CASE ...

Figure 4.30 Simple code generation with register numbering.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

Load_Mem b,R1Load_Mem b,R2Mult_Reg R2,R1Load_Const 4,R2Load_Mem a,R3Load_Mem c,R4Mult_Reg R4,R3Mult_Reg R3,R2Subtr_Reg R2,R1

Figure 4.31 Register machine code for the expression b*b - 4*(a*c).� �����������������������������������������������������������������������������������������������������������

144 SECTION 4.2 Code generation

Page 145: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

R1:

R2:

R4:

R3:

R1:

R2:

R4:

R3:

R1:

R2:

R3:

R4:

(1) (2) (3) (4)

(8)(7)(6)(5)

(9)

b

b

b b*b

4

b*b

c

(a*c)

4*(a*c)

b*bb*b

4

(a*c)

cc

a

4

b*b

a

4

b*b

c

(a*c)

4*(a*c)

b*b-4*(a*c)

b

Figure 4.32 Successive register contents for b*b - 4*(a*c).� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

Load_Mem b,R1Load_Mem b,R2Mult_Reg R2,R1Load_Mem a,R2Load_Mem c,R3Mult_Reg R3,R2Load_Const 4,R3Mult_Reg R3,R2Subtr_Reg R2,R1

Figure 4.33 Weighted register machine code for the expression b*b - 4*(a*c).� �����������������������������������������������������������������������������������������������������������

SUBSECTION 4.2.5 Code generation for basic blocks 145

Page 146: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

FUNCTION Weight of (Node) RETURNING an integer:SELECT Node .type:

CASE Constant type: RETURN 1;CASE Variable type: RETURN 1;CASE ...CASE Add type:

SET Required left TO Weight of (Node .left);SET Required right TO Weight of (Node .right);IF Required left > Required right: RETURN Required left;IF Required left < Required right: RETURN Required right;// Required left = Required rightRETURN Required left + 1;

CASE ...

Figure 4.34 Register requirements (weight) of a node.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

-

* *

b 4 *

a c

b 1

2

1

3

1

2

1

2

1

Figure 4.35 AST for b*b - 4*(a*c) with register weights.� �����������������������������������������������������������������������������������������������

146 SECTION 4.2 Code generation

Page 147: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

uses

R1,R2,R3

and one other reg.

R2 R3 R1

uses uses

R1andR1 R3

computation order

second parameter third parameter first parameter

Figure 4.36 Evaluation order of three parameter trees.� �����������������������������������������������������������������������������������������������

SUBSECTION 4.2.5 Code generation for basic blocks 147

Page 148: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

PROCEDURE Generate code for large trees (Node, Target register):SET Auxiliary register set TO

Available register set \ Target register;

WHILE Node /= No node:Compute the weights of all nodes of the tree of Node;SET Tree node TO Maximal non_large tree (Node);Generate code

(Tree node, Target register, Auxiliary register set);

IF Tree node /= Node:SET Temporary location TO Next free temporary location();Emit ("Store R" Target register ",T" Temporary location);Replace Tree node by a reference to Temporary location;Return any temporary locations in the tree of Tree node

to the pool of free temporary locations;ELSE Tree node = Node:

Return any temporary locations in the tree of Nodeto the pool of free temporary locations;

SET Node TO No node;

FUNCTION Maximal non_large tree (Node) RETURNING a node:IF Node .weight <= Size of Auxiliary register set: RETURN Node;IF Node .left .weight > Size of Auxiliary register set:

RETURN Maximal non_large tree (Node .left);ELSE Node .right .weight >= Size of Auxiliary register set:

RETURN Maximal non_large tree (Node .right);

Figure 4.37 Code generation for large trees.� �����������������������������������������������������������������������������������������������������������

148 SECTION 4.2 Code generation

Page 149: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

Load_Mem a,R1Load_Mem c,R2Mult_Reg R2,R1Load_Const 4,R2Mult_Reg R2,R1Store_Reg R1,T1Load_Mem b,R1Load_Mem b,R2Mult_Reg R2,R1Load_Mem T1,R2Subtr_Reg R2,R1

Figure 4.38 Code generated for b*b - 4*(a*c) with only 2 registers.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

-

* *

b 4 *

a c

b 1 1

2

1

2

1

0

0

1

Figure 4.39 Register-weighted tree for a memory-register machine.� �����������������������������������������������������������������������������������������������

SUBSECTION 4.2.5 Code generation for basic blocks 149

Page 150: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

Load_Const 4,R2Load_Mem a,R1Mult_Mem c,R1Mult_Reg R1,R2Load_Mem b,R1Mult_Mem b,R1Subtr_Reg R2,R1

Figure 4.40 Code for the register-weighted tree for a memory-register machine.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

{ int n;

n = a + 1;x = b + n*n + c;n = n + 1;y = d * n;

}

Figure 4.41 Sample basic block in C.� �����������������������������������������������������������������������������������������������������������

150 SECTION 4.2 Code generation

Page 151: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

+

a 1

=:

n +

1

=:

n

n

=:

y*

n

; ; ;

=:

+

+

b

n n

c

*

x

d

Figure 4.42 AST of the sample basic block.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

=:

+

+

b

n n

c

*

+

a 1

=:

n +

1

=:

n

n

=:

*

n

x

d

y

Figure 4.43 Data dependency graph for the sample basic block.� �����������������������������������������������������������������������������������������������

SUBSECTION 4.2.5 Code generation for basic blocks 151

Page 152: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

+

c+

b *

+

a 1

+

1

*

d

x y

Figure 4.44 Cleaned-up data dependency graph for the sample basic block.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

{ int n;

n = a + 1;x = b + n*n + c; /* subexpression n*n ... */n = n*n + 1; /* ... in common */y = d * n;

}

Figure 4.45 Basic block in C with common subexpression.� �����������������������������������������������������������������������������������������������������������

152 SECTION 4.2 Code generation

Page 153: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

+

c+

b *

+

a 1

+

1

*

d

*

x y

Figure 4.46 Data dependency graph with common subexpression.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

+

c+

b *

+

a 1

+

1

*

d

x y

Figure 4.47 Cleaned-up data dependency graph with common subexpression eliminated.� �����������������������������������������������������������������������������������������������

SUBSECTION 4.2.5 Code generation for basic blocks 153

Page 154: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

position triple1 a + 12 @1 * @13 b + @24 @3 + c5 @4 =: x6 @1 + 17 d * @68 @7 =: y

Figure 4.48 The data dependency graph of Figure 4.44 as an array of triples.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

+

+

b I1

c

Load_Mem b,R1

Add_Reg I1,R1

Add_Mem c,R1

Store_Reg R1,x

x

Figure 4.49 Rewriting and ordering a ladder sequence.� �����������������������������������������������������������������������������������������������

154 SECTION 4.2 Code generation

Page 155: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

+

c+

b *

+

a 1

+

1

*

d

x y

Figure 4.50 Cleaned-up data dependency graph for the sample basic block.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

+

c+

b *

+

a 1

x

Figure 4.51 Data dependency graph after removal of the first ladder sequence.� �����������������������������������������������������������������������������������������������

SUBSECTION 4.2.6 BURS code generation and dynamic programming 155

Page 156: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

+

a 1

X1

Figure 4.52 Data dependency graph after removal of the second ladder sequence.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

Load_Mem a,R1Add_Const 1,R1Load_Reg R1,X1

Load_Reg X1,R1Mult_Reg X1,R1Add_Mem b,R1Add_Mem c,R1Store_Reg R1,x

Load_Reg X1,R1Add_Const 1,R1Mult_Mem d,R1Store_Reg R1,y

Figure 4.53 Pseudo-register target code generated for the basic block.� �����������������������������������������������������������������������������������������������������������

156 SECTION 4.2 Code generation

Page 157: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

Load_Mem a,R1Add_Const 1,R1Load_Reg R1,R2

Load_Reg R2,R1Mult_Reg R2,R1Add_Mem b,R1Add_Mem c,R1Store_Reg R1,x

Load_Reg R2,R1Add_Const 1,R1Mult_Mem d,R1Store_Reg R1,y

Figure 4.54 Code generated for the program segment of Figure 4.41.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

Load_Mem a,R1Add_Const 1,R1Load_Reg R1,R2

Mult_Reg R1,R2Add_Mem b,R2Add_Mem c,R2Store_Reg R2,x

Add_Const 1,R1Mult_Mem d,R1Store_Reg R1,y

Figure 4.55 Code generated by the GNU C compiler, gcc.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 4.2.6 BURS code generation and dynamic programming 157

Page 158: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

{ int n;

n = a + 1;*x = b + n*n + c;n = n + 1;y = d * n;

}

Figure 4.56 Sample basic block with an assignment under a pointer.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

+

+

b

n n

c

*

+

a 1

=:

n +

1

=:

n

n

=:

*

n

x

d

y

=:*

Figure 4.57 Data dependency graph with an assignment under a pointer.� �����������������������������������������������������������������������������������������������

158 SECTION 4.2 Code generation

Page 159: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

+

a 1

+

c+

b *

=:*

x

=:

n

+

1

*

d

n

x y

Figure 4.58 Cleaned-up data dependency graph with an assignment under a pointer.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

Load_Mem a,R1Add_Const 1,R1Store_Reg R1,n

Load_Mem n,R1Mult_Mem n,R1Add_Mem b,R1Add_Mem c,R1Store_Indirect_Mem R1,x

Load_Mem n,R1Add_Const 1,R1Mult_Mem d,R1Store_Reg R1,y

Figure 4.59 Target code generated for the basic block of Figure 4.56.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 4.2.6 BURS code generation and dynamic programming 159

Page 160: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

1R

Rm

Rm

Rm

Mult_Scaled_Reg ,R ,R*#8 multiply scaled register cost = 5

R

Add_Scaled_Reg ,R ,R#7 add scaled register cost = 4

R

#6 m multiply registers cost = 4

R

Mult_Mem ,R#5 multiply from memory cost = 6

R

#4 Add_Reg R ,R1 add registers cost = 1

R

Add_Mem ,R#3 add from memory cost = 3

R

Load_Mem ,R#2 load from memory cost = 3

R

Load_Const ,R#1 load constant cost = 1

R

cst

+

+

*

*

+

R

R

R

R

R

R *

*

mem

mem

mem

cst

cst

cst

cst

cst

mem

mem

mem

n

n

n

n

n

n

n

n

n

n

n

n

n

n

n

n

n

n

n

n

n

n

Mult_Reg R ,R

m

m

#7.1

#8.1

Figure 4.60 Sample instruction patterns for BURS code generation.� �����������������������������������������������������������������������������������������������

160 SECTION 4.2 Code generation

Page 161: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

+

b *

4 *

8 a

Figure 4.61 Input tree for the BURS code generation.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

RR

8

*

*

R

R

+

a

4

b

#2#1

#1

#2

#6

#6

#4

Figure 4.62 Naive rewrite of the input tree.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

Load_Const 8,R1 ; 1 unitLoad_Mem a,R2 ; 3 unitsMult_Reg R2,R1 ; 4 unitsLoad_Const 4,R2 ; 1 unitMult_Reg R1,R2 ; 4 unitsLoad_Mem b,R1 ; 3 unitsAdd_Reg R2,R1 ; 1 unit

Total = 17 units

Figure 4.63 Code resulting from the naive rewrite.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 4.2.6 BURS code generation and dynamic programming 161

Page 162: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

R

b

*

4 *

R a

8

#5#2

#1

+ #7

Figure 4.64 Top-down largest-fit rewrite of the input tree.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

Load_Const 8,R1 ; 1 unitMult_Mem a,R1 ; 6 unitsLoad_Mem b,R2 ; 3 unitsAdd_Scaled_Reg 4,R1,R2 ; 4 units

Total = 14 units

Figure 4.65 Code resulting from the top-down largest-fit rewrite.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

1R1R

#7->reg #7.1

result

recognized

+

R

R *

cst

recognized

(b)

+

R

R *

(a)

cst

to be recognized

result

Figure 4.66 The dotted trees corresponding to #7→reg and to #7.1.� �����������������������������������������������������������������������������������������������

162 SECTION 4.2 Code generation

Page 163: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

PROCEDURE Bottom_up pattern matching (Node):IF Node is an operation:

Bottom_up pattern matching (Node .left);Bottom_up pattern matching (Node .right);SET Node .label set TO Label set for (Node);

ELSE IF Node is a constant:SET Node .label set TO Label set for constant ();

ELSE Node is a variable:SET Node .label set TO Label set for variable ();

FUNCTION Label set for (Node) RETURNING a label set:SET Label set TO the Empty set;FOR EACH Label IN the Machine label set:

FOR EACH Left label IN Node .left .label set:FOR EACH Right label IN Node .right .label set:

IF Label .operator = Node .operatorAND Label .operand = Left label .resultAND Label .second operand = Right label .result:Insert Label into Label set;

RETURN Label set;

FUNCTION Label set for constant () RETURNING a label set:SET Label set TO

{ (No operator, No location, No location, "Constant") };FOR EACH Label IN the Machine label set:

IF Label .operator = "Load" AND Label .operand = "Constant":Insert Label into Label set;

RETURN Label set;

FUNCTION Label set for variable () RETURNING a label set:SET Label set TO

{ (No operator, No location, No location, "Memory") };FOR EACH Label IN the Machine label set:

IF Label .operator = "Load" AND Label .operand = "Memory":Insert Label into Label set;

RETURN Label set;

Figure 4.67 Outline code for bottom-up pattern matching in trees.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 4.2.6 BURS code generation and dynamic programming 163

Page 164: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

TYPE operator: "Load", ’+’, ’*’;TYPE location: "Constant", "Memory", "Register", a label;

TYPE label: // a node in a pattern treean operator FIELD operator;a location FIELD operand;a location FIELD second operand;a location FIELD result;

Figure 4.68 Types for bottom-up pattern recognition in trees.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

->mem#2->reg

->cst#1->reg

#1->reg->cst

->mem#2->reg

#4->reg#7->reg

#6->reg#7.1#8->reg#8.1

#5->reg#6->reg#7.1#8.1

a8

4

b

+

*

*

Figure 4.69 Label sets resulting from bottom-up pattern matching.� �����������������������������������������������������������������������������������������������

164 SECTION 4.2 Code generation

Page 165: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

PROCEDURE Bottom_up pattern matching (Node):IF Node is an operation:

Bottom_up pattern matching (Node .left);Bottom_up pattern matching (Node .right);SET Node .state TO Next state

[Node .operand, Node .left .state, Node .right .state];ELSE IF Node is a constant:

SET Node .state TO State for constant;ELSE Node is a variable:

SET Node .state TO State for variable;

Figure 4.70 Outline code for efficient bottom-up pattern matching in trees.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

a8

4

b

+

#7.1#8->reg @9

#7.1#8.1

#4->reg @13

#5->reg @7

->cst @0#1->reg @1

->mem @0#2->reg @3

#1->reg @1->cst @0

->mem @0#2->reg @3

✔✔

*

*

Figure 4.71 Bottom-up pattern matching with costs.� �����������������������������������������������������������������������������������������������

SUBSECTION 4.2.7 Register allocation by graph coloring 165

Page 166: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

Load_Mem a,R1 ; 3 unitsLoad_Const 4,R2 ; 1 unitMult_Scaled_Reg 8,R1,R2 ; 5 unitsLoad_Mem b,R1 ; 3 unitsAdd_Reg R2,R1 ; 1 unit

Total = 13 units

Figure 4.72 Code generated by bottom-up pattern matching.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

Load_Mem a,R1 ; 3 unitsLoad_Const 4,R2 ; 1 unitMult_Scaled_Reg 8,R1,R2 ; 5 unitsAdd_Mem b,R1 ; 3 units

Total = 12 units

Figure 4.73 Code generated by bottom-up pattern matching, using commutativity.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

S00 = {}S01 = {→cst@0, #1→reg@1}S02 = {→mem@0, #2→reg@3}S03 = {#4→reg@0}S04 = {#6→reg@5, #7.1@0, #8.1@0}S05 = {#3→reg@0}S06 = {#5→reg@4, #7.1@0, #8.1@0}S07 = {#6→reg@0}S08 = {#5→reg@0}S09 = {#7→reg@0}S10 = {#8→reg@1, #7.1@0, #8.1@0}S11 = {#8→reg@0}S12 = {#8→reg@2, #7.1@0, #8.1@0}S13 = {#8→reg@4, #7.1@0, #8.1@0}

Figure 4.74 States of the BURS automaton for Figure 4.60.� �����������������������������������������������������������������������������������������������������������

166 SECTION 4.2 Code generation

Page 167: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

cst: S01mem: S02

Figure 4.75 Initial states for the basic operands.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

’+’ S01 S02 S03 S04 S05 S06 S07 S08 S09 S10 S11 S12 S13� ���������������������������������������������������������������������������������������������������������������������������������������������������������������������

S01- S03 S05 S03 S09 S03 S09 S03 S03 S03 S03 S03 S03 S09S13

�����

’*’ S01 S02 S03 S04 S05 S06 S07 S08 S09 S10 S11 S12 S13� ���������������������������������������������������������������������������������������������������������������������������������������������������������������������

S01 S04 S06 S04 S10 S04 S12 S04 S04 S04 S04 S04 S13 S12S02- S07 S08 S07 S11 S07 S11 S07 S07 S07 S07 S07 S11 S11S13

�������

Figure 4.76 The transition table Cost conscious next state[].� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

S01 S02 S03 S04 S05 S06 S07 S08 S09 S10 S11 S12 S13cst -- -- -- -- -- -- -- -- -- -- -- --mem -- -- -- -- -- -- -- -- -- -- -- --reg #1 #2 #4 #6 #3 #5 #6 #5 #7 #8 #8 #8 #8

�����

Figure 4.77 The code generation table.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 4.2.11 Preprocessing the intermediate code 167

Page 168: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

S03

S02 S12

S01 S06

S01 S02

+

*

*

8 a

4

b#2

#4

#1

#8

#2-

Figure 4.78 States and instructions used in BURS code generation.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

a := read();b := read();c := read();a := a + b + c;if (a < 10) {

d := c + 8;print(c);

} else if (a < 20) {e := 10;d := e + a;print(e);

} else {f := 12;d := f + a;print(f);

}print(d);

Figure 4.79 A program segment for live analysis.� �����������������������������������������������������������������������������������������������������������

168 SECTION 4.2 Code generation

Page 169: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

a := read();

a := a+b+c;

c := read();

b := read();

d := c+8;

print(c);

f := 12;

d := f+a;

print(f);

e := 10;

d := e+a;

print(e);

a < 10

a < 20

a

c

b

e

d

d

f

print(d);

d

Figure 4.80 Live ranges of the variables from Figure 4.79.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

f a

d e c

b

Figure 4.81 Register interference graph for the variables of Figure 4.79.� �����������������������������������������������������������������������������������������������

SUBSECTION 4.2.12 Postprocessing the target code 169

Page 170: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

FUNCTION Color graph (Graph) RETURNING the Colors used set:IF Graph = the Empty graph: RETURN the Empty set;

// Find the Least connected node:SET Least connected node TO No node;FOR EACH Node IN Graph .nodes:

SET Degree TO 0;FOR EACH Arc IN Graph .arcs:

IF Arc contains Node:Increment Degree;

IF Least connected node = No node ORDegree < Minimum degree:SET Least connected node TO Node;SET Minimum degree TO Degree;

// Remove Least connected node from Graph:SET Least connected node arc set TO the Empty set;FOR EACH Arc IN Graph .arcs:

IF Arc contains Least connected node:Remove Arc from Graph .arcs;Insert Arc in Least connected node arc set;

Remove Least connected node from Graph .nodes;

// Color the reduced Graph recursively:SET Colors used set TO Color graph (Graph);

// Color the Least connected node:SET Left over colors set TO Colors used set;FOR EACH Arc IN Least connected node arc set:

FOR EACH End point IN Arc:IF End point /= Least connected node:

Remove End point .color from Left over colors set;IF Left over colors set = Empty:

SET Color TO New color;Insert Color in Colors used set;Insert Color in Left over colors set;

SET Least connected node .color TOArbitrary choice from Left over colors set;

// Reattach the Least connected node:Insert Least connected node in Graph .nodes;FOR EACH Arc IN Least connected node arc set:

Insert Arc in Graph .arcs;RETURN Colors used set;

Figure 4.82 Outline of a graph coloring algorithm.� �����������������������������������������������������������������������������������������������������������

170 SECTION 4.2 Code generation

Page 171: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

f

d e

f

d

f a

d e

c b

f a

d e c

b

f a

d e c

b

f

d

e a c b

f

d e

a c b

f a

d e

c b

f a

d e c

b

f a

d e c

b

Graph:

a c b e a c bStack:

1 1 1 1

1 1 1 12 2 2 2

22 1 2 3

2 1 1

f

d e a c b f d e a c b

f

d e a c b

1

Figure 4.83 Coloring the interference graph for the variables of Figure 4.79.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

; n in register %axcwd ; convert to double word:

; (%dx,%ax) = (extend_sign(%ax), %ax)negw %ax ; negate: (%ax,cf) := (-%ax, %ax /= 0)adcw %dx,%dx ; add with carry: %dx := %dx + %dx + cf

; sign(n) in %dx

Figure 4.84 Optimal code for the function sign(n).� �����������������������������������������������������������������������������������������������������������

SECTION 4.4 Conclusion 171

Page 172: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

Case n > 0 Case n = 0 Case n < 0%dx %ax cf %dx %ax cf %dx %ax cf

initially:− n − − 0 − − n −

cwd0 n − 0 0 − -1 n −

negw %ax0 -n 1 0 0 0 -1 -n 1

adcw %dx,%dx1 -n 1 0 0 0 -1 -n 1

Figure 4.85 Actions of the 80x86 code from Figure 4.84.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

Problem Technique Quality

Expression trees, usingregister-register ormemory-register instruc-tions

Weighted trees;Figure 4.30

with sufficient registers: Optimalwith insufficient registers: Optimal

HeuristicDependency graphs, usingregister-register ormemory-register instruc-tions

Ladder sequences;Section 4.2.5.2

Expression trees, using anyinstructions with cost func-tion

Bottom-up tree rewrit-ing;Section 4.2.6

with sufficient registers: Optimalwith insufficient registers: Heuristic

HeuristicRegister allocation when allinterferences are known

Graph coloring;Section 4.2.7

Figure 4.86 Comparison of some code generation techniques.� �����������������������������������������������������������������������������������������������

172 CHAPTER 4 Processing the intermediate code

Page 173: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

int i, A[10];

for (i = 0; i < 20; i++) {A[i] = 2*i;

}

Figure 4.87 Incorrect C program with compilation-dependent effect.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

operation ⇒ replacementE * 2 ** n ⇒ E << n2 * V ⇒ V + V3 * V ⇒ (V << 1) + VV ** 2 ⇒ V * V

E + 0 ⇒ EE * 1 ⇒ EE ** 1 ⇒ E1 ** E ⇒ 1

Figure 4.88 Some transformations for arithmetic simplification.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

void S {...print_square(i++);...

}

void print_square(int n) {printf("square = %d\n", n*n);

}

Figure 4.89 C code with a routine to be in-lined.� �����������������������������������������������������������������������������������������������������������

SECTION 4.4 Conclusion 173

Page 174: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

void S {...{int n = i++; printf("square = %d\n", n*n);}...

}

void print_square(int n) {printf("square = %d\n", n*n);

}

Figure 4.90 C code with the routine in-lined.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

bit maps

C

C

C

relocation

1000

4000

4500

0

250

400

1600

0

1000

0

3000

0

a.o

b.o

printf.o100

500

entry point_printf

reference to_printf

segmentsoriginal code

4100

2600

1250

1400

0

segmentexecutable code

resulting

Figure 4.91 Linking three code segments.� �����������������������������������������������������������������������������������������������

174 CHAPTER 4 Processing the intermediate code

Page 175: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

.data....align 8

var1:.long 666...

.code...addl var1,%eax...jmp label1...

label1:......

Figure 4.92 Assembly code fragment with internal symbols.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

Assemblycode

Backpatch listfor label1

Assembledbinary

EA

EA

0

0

EA 0

. . . .

jmp label1

. . . .

. . . .

. . . .

jmp label1

. . . .

label1:

. . . .

jmp label1

. . . .

Figure 4.93 A backpatch list for labels.� �����������������������������������������������������������������������������������������������

SECTION 4.4 Conclusion 175

Page 176: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

External symbol Type Address

_options entry point 50 data__main entry point 100 code_printf reference 500 code_atoi reference 600 code_printf reference 650 code_exit reference 700 code_msg_list entry point 300 data_Out_Of_Memory entry point 800 code_fprintf reference 900 code_exit reference 950 code_file_list reference 4 data

Figure 4.94 Example of an external symbol table.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

Figure 4.95 Test graph for recursive descent marking.� �����������������������������������������������������������������������������������������������

176 CHAPTER 4 Processing the intermediate code

Page 177: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

void Routine(void) {if (...) {

while (...) {A;

}}else {

switch (...) {case: ...: B; break;case: ...: C; break;}

}}

Figure 4.96 Routine code for static profiling.� �����������������������������������������������������������������������������������������������������������

SECTION 4.4 Conclusion 177

Page 178: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

A

if

end if

while

CB

switch

end switch

a

cb

d

e f

g

h

ji k

l m n

po

q

1

Figure 4.97 Flow graph for static profiling of Figure 4.96.� �����������������������������������������������������������������������������������������������

178 CHAPTER 4 Processing the intermediate code

Page 179: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

5�������������������������������������������������������������������������

Memory management

179

Page 180: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

zis

chunk

i

ez

s

e

block

size

0

in use . . . . . . .

chunk

low high

marked in use marked free

1

not in use

block

Figure 5.1 Memory structure used by the malloc/free mechanism.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

SET the polymorphic chunk pointer First_chunk pointer TOBeginning of available memory;

SET the polymorphic chunk pointer One past available memory TOBeginning of available memory + Size of available memory;

SET First_chunk pointer .size TO Size of available memory;SET First_chunk pointer .free TO True;

FUNCTION Malloc (Block size) RETURNING a polymorphic block pointer:SET Pointer TO Pointer to free block of size (Block size);IF Pointer /= Null pointer: RETURN Pointer;

Coalesce free chunks;SET Pointer TO Pointer to free block of size (Block size);IF Pointer /= Null pointer: RETURN Pointer;

RETURN Solution to out of memory condition (Block size);

PROCEDURE Free (Block pointer):SET Chunk pointer TO Block pointer - Administration size;SET Chunk pointer .free TO True;

Figure 5.2 A basic implementation of Malloc(Block size).� �����������������������������������������������������������������������������������������������������������

180 SECTION 5.1 Data allocation with explicit deallocation

Page 181: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

FUNCTION Pointer to free block of size (Block size)RETURNING a polymorphic block pointer:// Note that this is not a pure functionSET Chunk pointer TO First_chunk pointer;SET Requested chunk size TO Administration size + Block size;

WHILE Chunk pointer /= One past available memory:IF Chunk pointer .free:

IF Chunk pointer .size - Requested chunk size >= 0:// large enough chunk found:Split chunk (Chunk pointer, Requested chunk size);SET Chunk pointer .free TO False;RETURN Chunk pointer + Administration size;

// try next chunk:SET Chunk pointer TO Chunk pointer + Chunk pointer .size;

RETURN Null pointer;

PROCEDURE Split chunk (Chunk pointer, Requested chunk size):SET Left_over size TO Chunk pointer .size - Requested chunk size;IF Left_over size > Administration size:

// there is a non-empty left-over chunkSET Chunk pointer .size TO Requested chunk size;SET Left_over chunk pointer TO

Chunk pointer + Requested chunk size;SET Left_over chunk pointer .size TO Left_over size;SET Left_over chunk pointer .free TO True;

PROCEDURE Coalesce free chunks:SET Chunk pointer TO First_chunk pointer;

WHILE Chunk pointer /= One past available memory:IF Chunk pointer .free:

Coalesce with all following free chunks (Chunk pointer);SET Chunk pointer TO Chunk pointer + Chunk pointer .size;

PROCEDURE Coalesce with all following free chunks (Chunk pointer):SET Next_chunk pointer TO Chunk pointer + Chunk pointer .size;WHILE Next_chunk pointer /= One past available memory

AND Next_chunk pointer .free:// Coalesce them:SET Chunk pointer .size TO

Chunk pointer .size + Next_chunk pointer .size;SET Next_chunk pointer TO Chunk pointer + Chunk pointer .size;

Figure 5.3 Auxiliary routines for the basic Malloc(Block size).� �����������������������������������������������������������������������������������������������������������

SUBSECTION 5.1.1 Basic memory allocation 181

Page 182: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

SET Free list for T TO No T;

FUNCTION New T () RETURNING a pointer to an T:IF Free list for T = No T:

// Acquire a new block of records:SET New block [1 .. Block factor for T] TO

Malloc (Size of T * Block factor for T);// Construct a free list in New block:SET Free list for T TO address of New block [1];FOR Record count IN [1 .. Block factor for T - 1]:

SET New block [Record count] .link TOaddress of New block [Record count + 1];

SET New block [Block factor for T] .link TO No T;

// Extract a new record from the free list:SET New record TO Free list for T;SET Free list for T TO New record .link;

// Zero the New record here, if required;RETURN New record;

PROCEDURE Free T (Old record):// Prepend Old record to free list:SET Old record .link TO Free list for T;SET Free list for T TO address of Old record;

Figure 5.4 Outline code for blockwise allocation of records of type T.� �����������������������������������������������������������������������������������������������������������

182 SECTION 5.2 Data allocation with implicit deallocation

Page 183: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

.

.

.

.

.

.

.

.

.

.

.

.

inuse

inuse

inuse

inuse

free_list_Elem

block k

block 1

free free free

free

Figure 5.5 List of free records in allocated blocks.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

a

c

d

b

f

e

heap

root set

Figure 5.6 A root set and a heap with reachable and unreachable chunks.� �����������������������������������������������������������������������������������������������

SUBSECTION 5.2.4 Mark and scan 183

Page 184: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

2

2

1

1

2

heaparea

1

programdata

a

b

c

d

e

f

Figure 5.7 Chunks with reference count in a heap.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

2

1

1

0

1

heaparea

0

programdata

a d

c

f

Figure 5.8 Result of removing the reference to chunk b in Figure 5.7.� �����������������������������������������������������������������������������������������������

184 SECTION 5.2 Data allocation with implicit deallocation

Page 185: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

IF Points into the heap (q):Increment q .reference count;

IF Points into the heap (p):Decrement p .reference count;IF p .reference count = 0:

Free recursively depending on reference counts (p);SET p TO q;

Figure 5.9 Code to be generated for the pointer assignment p:=q.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

PROCEDURE Free recursively depending on reference counts(Pointer);WHILE Pointer /= No chunk:

IF NOT Points into the heap (Pointer): RETURN;IF NOT Pointer .reference count = 0: RETURN;

FOR EACH Index IN 1 .. Pointer .number of pointers - 1:Free recursively depending on reference counts

(Pointer .pointer [Index]);

SET Aux pointer TO Pointer;IF Pointer .number of pointers = 0:

SET Pointer TO No chunk;ELSE Pointer .number of pointers > 0:

SET Pointer TOPointer .pointer [Pointer .number of pointers];

Free chunk(Aux pointer); // the actual freeing operation

Figure 5.10 Recursively freeing chunks while avoiding tail recursion.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 5.2.6 Compaction 185

Page 186: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

1

1

1

1

heaparea

programdata

a

c

d

f

Figure 5.11 Reference counting fails to identify circular garbage.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

4

free

321size

bitmarked

bit

op

io

n nt

e er

po

i int

p

rr

to parent

3

0

3rd child

. . . . . . . . . .

to parent

1 nter

poi

e

counterpointer

t

Figure 5.12 Marking the third child of a chunk.� �����������������������������������������������������������������������������������������������

186 SECTION 5.2 Data allocation with implicit deallocation

Page 187: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

0

C

Parentpointer

Chunkpointer

P

Figure 5.13 The Schorr and Waite algorithm, arriving at C.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

n

C

Parentpointer

Chunkpointer

P

n

-th pointer

D

0

Figure 5.14 Moving to D.� �����������������������������������������������������������������������������������������������

SECTION 5.3 Conclusion 187

Page 188: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

Number of pointers in

n

D

C

Parentpointer

Chunkpointer

P

n

-th pointer

D

Figure 5.15 About to return from D.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

Number of pointers in C

C

Parentpointer

Chunkpointer

P

Figure 5.16 About to return from C.� �����������������������������������������������������������������������������������������������

188 CHAPTER 5 Memory management

Page 189: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

to spacefrom spaceprogram data area

program data area to space from space

Figure 5.17 Memory layout for two-space copying.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

a

c

from-space

to-space

b

f

eroot set

d

Figure 5.18 Initial situation in two-space copying.� �����������������������������������������������������������������������������������������������

SECTION 5.3 Conclusion 189

Page 190: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

a cb

from-space

to-space

f

eroot set

scan pointer

d

Figure 5.19 Snapshot after copying the first level.� �����������������������������������������������������������������������������������������������

190 CHAPTER 5 Memory management

Page 191: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

a cb

from-space

to-space

f

eroot set

d

scan pointer

Figure 5.20 Snapshot after having scanned one chunk.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

1

1 2

2

old

new

new address of 1

garbage garbagechunk chunk

Figure 5.21 Address calculation during compaction.� �����������������������������������������������������������������������������������������������

SECTION 5.3 Conclusion 191

Page 192: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

2

1 2

1

new address of 1

garbage chunk garbage chunk

new

old

new address of 2

Figure 5.22 Pointer update during compaction.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

2 free1

old

new

Figure 5.23 Moving the chunks during compaction.� �����������������������������������������������������������������������������������������������

192 CHAPTER 5 Memory management

Page 193: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

6�������������������������������������������������������������������������

Imperative and object-oriented programs

193

Page 194: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

Imperativeand object-oriented

Functional Logic Parallel anddistributed�

���

����

����

� ������������������������������������������������������������������������������������������������������������������������������������������ �����������������������������������������������������������������������������������������������������������������������������������������

general: 2� �������������������������������������������������������������������������������������������������������������������

specific: −

Lexical andsyntacticanalysis,� ������������������������������������������������������������������������������������������������������������������������������������������ �����������������������������������������������������������������������������������������������������������������������������������������

general: 3� �������������������������������������������������������������������������������������������������������������������identification &type checking:

6.1� �������������������������������������������������������������������������������������������������������������������

6 7 8 9

Contexthandling,

specific: ��

��

��

� ������������������������������������������������������������������������������������������������������������������������������������������ �����������������������������������������������������������������������������������������������������������������������������������������general: 4� �������������������������������������������������������������������������������������������������������������������

6 7 8 9Codegeneration, specific:� ������������������������������������������������������������������������������������������������������������������������������������������ �����������������������������������������������������������������������������������������������������������������������������������������

��������������

������������������

��

��

��

Figure 6.1 Roadmap to paradigm-specific issues.� �����������������������������������������������������������������������������������������������

194 SECTION 6.1 Context handling

Page 195: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

P

P

P

P

P

P

P

P

P

P

"wrong" "right"

"signal" "matt"

"right" "left"

"paint" "rotate"

"printf" "signal"

level

4

3

2

1

0

scope stack

. . .

. . .

. . .

properties

name

Figure 6.2 A naive scope-structured symbol table.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

void rotate(double angle) {...

}

void paint(int left, int right) {Shade matt, signal;

...{ Counter right, wrong;

...}

}

Figure 6.3 C code leading to the symbol table in Figure 6.2.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 6.1.2 Type checking 195

Page 196: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

Pdecl

macro

name

decl P

macro

name

Pdecl

macro

name

2 P

properties

level

Id.info

"paint"

"signal"

"right"

1

3 0 P

4

hash table

Figure 6.4 A hash-table based symbol table.� �����������������������������������������������������������������������������������������������

196 SECTION 6.2 Source language data representation and handling

Page 197: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

level

4

3

2

1

0

scope stack

Id.info("wrong")

Id.info("signal")

Id.info("right")

Id.info("paint")

Id.info("printf")

. . .

. . .

. . .

Id.info("right")

Id.info("matt")

Id.info("left")

Id.info("rotate")

Id.info("signal")

Figure 6.5 Scope table for the hash-table based symbol table.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

PROCEDURE Remove topmost scope ():SET Link pointer TO Scope stack [Top level];WHILE Link pointer /= No link:

// Get the next Identification info recordSET Idf pointer TO Link pointer .idf_info;SET Link pointer TO Link pointer .next;// Get its first Declaration info recordSET Declaration pointer TO Idf pointer .decl;// Now Declaration pointer .level = Top level// Detach the first Declaration info recordSET Idf pointer .decl TO Declaration pointer .next;Free the record pointed at by Declaration pointer;

Free Scope stack [Top level];SET Top level TO Top level - 1;

Figure 6.6 Outline code for removing declarations at scope exit.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 6.2.6 Array types 197

Page 198: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

P P

"zout" "sel"

. . .selectors

type record

T:

Figure 6.7 Finding the type of a selector.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

Data definitions:1. Let T be a type table that has entries containing either a type description or areference (TYPE) to a type table entry.2. Let Cyclic be a set of type table entries.

Initializations:Initialize the Cyclic set to empty.

Inference rules:If there exists a TYPE type table entry t 1 in T and t 1 is not a member ofCyclic, let t 2 be the type table entry referred to by t 1 .1. If t 2 is t 1 then add t 1 to Cyclic.2. If t 2 is a member of Cyclic then add t 1 to Cyclic.3. If t 2 is again a TYPE type table entry, replace, in t 1 , the reference to t 2 withthe reference referred to by t 2 .

Figure 6.8 Closure algorithm for detecting cycles in type definitions.� �����������������������������������������������������������������������������������������������

198 SECTION 6.2 Source language data representation and handling

Page 199: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

Data definitions:Let each node in the expression have a variable type set S attached to it. Also,each node is associated with a non-variable context C.

Initializations:The type set S of each operator node contains the result types of all identifica-tions of the operator in it; the type set S of each leaf node contains the types ofall identifications of the node. The context C of a node derives from thelanguage manual.

Inference rules:For each node N with context C, if its type set S contains a type T 1 which thecontext C allows to be coerced to a type T 2 , T 2 must also be present in S.

Figure 6.9 The closure algorithm for identification in the presence of overloading and coercions,phase 1.

� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

Data definitions:Let each node in the expression have a type set S attached to it.

Initializations:Let the type set S of each node be filled by the algorithm of Figure 6.9.

Inference rules:1. For each operator node N with type set S, if S contains a type T such thatthere is no operator identified in N that results in T and has operands T 1 andT 2 such that T 1 is in the type set of the left operand of N and T 2 is in the typeset of the right operand of N, T is removed from S.2. For each operand node N with type set S, if S contains a type T that is notcompatible with at least one type of the operator that works on N, T is removedfrom S.

Figure 6.10 The closure algorithm for identification in the presence of overloading and coercions,phase 2.

� �����������������������������������������������������������������������������������������������

SUBSECTION 6.2.9 Object types 199

Page 200: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

:=

(location of)p

deref

(location of)q

Figure 6.11 AST for p := q with explicit deref.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

expected��lvalue rvalue

� ���������������������������������������������������������

lvalue − dereffound

rvalue error −���

Figure 6.12 Basic checking rules for lvalues and rvalues.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

expression resultingconstruct kind

constant rvalueidentifier (variable) lvalueidentifier (otherwise) rvalue&lvalue rvalue*rvalue lvalueV[rvalue] VV.selector Vrvalue+rvalue rvaluelvalue:=rvalue rvalue

Figure 6.13 lvalue/rvalue requirements and results of some expression constructs.� �����������������������������������������������������������������������������������������������������������

200 SECTION 6.2 Source language data representation and handling

Page 201: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

void do_buffer(void) {char *buffer;

obtain_buffer(&buffer);use_buffer(buffer);

}

void obtain_buffer(char **buffer_pointer) {char actual_buffer[256];

*buffer_pointer = &actual_buffer;/* this is a scope-violating assignment: *//* scope of *buffer_pointer > scope of &actual_buffer */

}

Figure 6.14 Example of a scope violation in C.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

B[1,2]

(b)(a)

B[1,1]

B[2,1]

B[1,2]

B[2,2]

B[1,1]

B[1,3]

B[2,1]

B[2,2]

B[2,3] B[2,3]

B[1,3]

Figure 6.15 Array B in row-major (a) and column-major (b) order.� �����������������������������������������������������������������������������������������������

SUBSECTION 6.3.3 Operations on routines 201

Page 202: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

n

LEN

LB

LEN_PRODUCT

zeroth_element

LBn

. . .

LENn

LEN_PRODUCTn

1

1

1

Figure 6.16 An array descriptor.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

dispatch table

a1

a2

pointer to Bpointer to A inside B

b1

B-object

m1_A_A

m2_A_B

m3_B_B

B-class

Figure 6.17 The representation of an object of class B.� �����������������������������������������������������������������������������������������������

202 SECTION 6.3 Routines and their activation

Page 203: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

class C {field c1;field c2;method m1();method m2();

};

class D {field d1;method m3();method m4();

};

class E extends C, D {field e1;method m2();method m4();method m5();

};

Figure 6.18 An example of multiple inheritance.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

dispatch table

m5_E_E

pointer to Epointer to C inside E

pointer to D inside E

c1

c2

d1

e1

E-object E-class

m1_C_C

m2_C_E

m3_D_D

m4_D_E

Figure 6.19 A representation of an object of class E.� �����������������������������������������������������������������������������������������������

SUBSECTION 6.3.5 Nested routines 203

Page 204: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

class A {field a1;field a2;method m1();method m3();

};

class C extends A {field c1;field c2;method m1();method m2();

};

class D extends A {field d1;method m3();method m4();

};

class E extends C, D {field e1;method m2();method m4();method m5();

};

Figure 6.20 An example of dependent multiple inheritance.� �����������������������������������������������������������������������������������������������������������

204 SECTION 6.3 Routines and their activation

Page 205: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

E-class

c2

c1

a2

a1

2 3 4 5 8 9 -4 -3 2

dispatch table

e1

d1

m1_A_Cpointer to E

pointer to C inside E

pointer to D inside E

m1_A_A

m5_E_E

E-object

m3_A_A

m2_C_E

m3_A_D

m4_D_E

index tables

Figure 6.21 An object of class E, with dependent inheritance.� �����������������������������������������������������������������������������������������������

SUBSECTION 6.3.5 Nested routines 205

Page 206: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

adm

inis

trat

ive

part

addresseshigh

addresses

parameter k

parameter 1

.

.

dynamic link

registers & misc.

local variables

working stack

frame pointer

stack pointer

FP

SP

return information

lexical pointer

low

Figure 6.22 Possible structure of an activation record.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

void use_iterator(void) {int i;

while ((i = get_next_int()) > 0) {printf("%d\n", i);

}}

int get_next_int(void) {yield 8;yield 3;yield 0;

}

Figure 6.23 An example application of an iterator in C notation.� �����������������������������������������������������������������������������������������������������������

206 SECTION 6.3 Routines and their activation

Page 207: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

char buffer[100];

void Producer(void) {while (produce_buffer()) {

resume(Consumer);}empty_buffer(); /* signal end of stream */resume(Consumer);

}

void Consumer(void) {resume(Producer);while (!empty_buffer_received()) {

consume_buffer();resume(Producer);

}}

Figure 6.24 Simplified producer/consumer communication using coroutines.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

int i;

void level_0(void) {int j;

void level_1(void) {int k;

void level_2(void) {int l;

... /* code has access to i, j, k, l */k = l;j = l;

}

... /* code has access to i, j, k */j = k;

}

... /* code has access to i, j */}

Figure 6.25 Nested routines in C notation.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 6.3.5 Nested routines 207

Page 208: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

void level_0(void) {

void level_1(void) {

void level_2(void) {

...goto L_1;...

}

...L_1:...

...}

...}

Figure 6.26 Example of a non-local goto.� �����������������������������������������������������������������������������������������������������������

208 SECTION 6.3 Routines and their activation

Page 209: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

#include <setjmp.h>

void find_div_7(int n, jmp_buf *jmpbuf_ptr) {if (n % 7 == 0) longjmp(*jmpbuf_ptr, n);find_div_7(n + 1, jmpbuf_ptr);

}

int main(void) {jmp_buf jmpbuf; /* type defined in setjmp.h */int return_value;

if ((return_value = setjmp(jmpbuf)) == 0) {/* setting up the label for longjmp() lands here */find_div_7(1, &jmpbuf);

}else {

/* returning from a call of longjmp() lands here */printf("Answer = %d\n", return_value);

}return 0;

}

Figure 6.27 Demonstration of the setjmp/longjmp mechanism.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

routine address

lexical pointer

Figure 6.28 A routine descriptor for a language that requires lexical pointers.� �����������������������������������������������������������������������������������������������

SUBSECTION 6.4.1 Local flow of control 209

Page 210: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

void level_1(void) {int k;

void level_2(void) {int l;

...}routine_descriptor level_2_as_a_value = {

FP_of_this_activation_record(), /* FP of level_1() */level_2 /* code address of level_2()*/

};

A(level_2_as_a_value); /* level_2() as a parameter */}

Figure 6.29 Possible code for the construction of a routine descriptor.� �����������������������������������������������������������������������������������������������������������

210 SECTION 6.4 Code generation for control flow statements

Page 211: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

Activation record oflexical parent of R

Adm. part

Activation record oflexical parent of R

Activation record ofQ Rthe caller of

Activation record ofRQthe caller of

code of Q

code of R

code of Q

code of R

FP

FP

Adm. part. . .

Dlexical ptr

routine addr

PC

Adm. part

Adm. part

D

Activation record R

PC

lexical ptrreturn addr

dynamic link

of

b. After calling . Ra. Before calling . R

Figure 6.30 Calling a routine defined by the two-pointer routine descriptor D.� �����������������������������������������������������������������������������������������������

SUBSECTION 6.4.1 Local flow of control 211

Page 212: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

*(*(

FP+offset(lexical_pointer)

)+offset(k)

) =*(FP + offset(l))

Figure 6.31 Intermediate code for the non-local assignment k = l.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

*(*(

*( FP+offset(lexical_pointer)

)+offset(lexical_pointer)

)+offset(j)

) =*(FP + offset(l))

Figure 6.32 Intermediate code for the non-local assignment j = l.� �����������������������������������������������������������������������������������������������������������

212 SECTION 6.4 Code generation for control flow statements

Page 213: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

activation record oflevel_1()

level_2()code of

lex ptr to level_0()

activation record

activation record

activation record oflevel_2()

lex ptr to level_1()

nested routine

passed as a parameterlevel_2()

Figure 6.33 Passing a nested routine as a parameter and calling it.� �����������������������������������������������������������������������������������������������

SUBSECTION 6.4.2 Routine invocation 213

Page 214: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

void level_1(void) {non_local_label_descriptor L_1_as_a_value = {

FP_of_this_activation_record(), /* FP of level_1() */L_1 /* code address of L_1 */

};

void level_2(void) {

...non_local_goto(L_1_as_a_value); /* goto L_1; */...

}

...L_1:...

...}

Figure 6.34 Possible code for the construction of a label descriptor.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

addresseshigh

value of param. 2

value of param. 4

01010

lexical pointer

routine address

Figure 6.35 A closure for a partially parameterized routine.� �����������������������������������������������������������������������������������������������

214 SECTION 6.4 Code generation for control flow statements

Page 215: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

int i;

void level_2(int *j, int *k) {int l;

... /* code has access to i, *j, *k, l */*k = l;*j = l;

}

void level_1(int *j) {int k;

... /* code has access to i, *j, k */level_2(j, &k); /* was: level_2(); */A(level_2); /* level_2() as a parameter: */

/* this is a problem */}

void level_0(void) {int j;

... /* code has access to i, j */level_1(&j); /* was: level_1(); */

}

Figure 6.36 Lambda-lifted routines in C notation.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 6.5.3 Code generation for generics 215

Page 216: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

int i;

void level_2(int *j, int *k) {int l;

... /* code has access to i, *j, *k, l */*k = l;*j = l;

}

void level_1(int *j) {int *k = (int *)malloc(sizeof (int));

... /* code has access to i, *j, *k */level_2(j, k); /* was: level_2(); */A(closure(level_2, j, k)); /* was: A(level_2); */

}

void level_0(void) {int *j = (int *)malloc(sizeof (int));

... /* code has access to i, *j */level_1(j); /* was: level_1(); */

}

Figure 6.37 Lambda-lifted routines with additional heap allocation in C notation.� �����������������������������������������������������������������������������������������������������������

216 CHAPTER 6 Imperative and object-oriented programs

Page 217: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

PROCEDURE Generate code for Boolean control expression (Node, True label, False label

):SELECT Node .type:

CASE Comparison type: // <, >, ==, etc. in CGenerate code for comparison expression (Node .expr);// The comparison result is now in the condition registerIF True label /= No label:

Emit ("IF condition register THEN GOTO" True label);IF False label /= No label:

Emit ("GOTO" False label);ELSE True label = No label:

IF False label /= No label:Emit ("IF NOT condition register THEN GOTO"

False label);CASE Lazy and type: // the && in C

Generate code for Boolean control expression(Node .left, No label, False label);

Generate code for Boolean control expression(Node .right, True label, False label);

CASE ...CASE Negation type: // the ! in C

Generate code for Boolean control expression(Node, False label, True label);

Figure 6.38 Code generation for Boolean expressions.� �����������������������������������������������������������������������������������������������������������

SECTION 6.6 Conclusion 217

Page 218: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

tmp_case_value := case expression;IF tmp_case_value = I 1 THEN GOTO label_1;...IF tmp_case_value = In THEN GOTO label_n;GOTO label_else; // or insert the code at label_else

label_1:code for statement sequence 1

GOTO label_next;...

label_n:code for statement sequencen

GOTO label_next;label_else:

code for else-statement sequencelabel_next:

Figure 6.39 A simple translation scheme for case statements.� �����������������������������������������������������������������������������������������������������������

218 CHAPTER 6 Imperative and object-oriented programs

Page 219: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

i := lower bound;tmp_ub := upper bound;tmp_step_size := step_size;IF tmp_step_size = 0 THEN

... probably illegal; cause run-time error ...IF tmp_step_size < 0 THEN GOTO neg_step;IF i > tmp_ub THEN GOTO end_label;// the next statement uses tmp_ub - i// to evaluate tmp_loop_count to its correct, unsigned valuetmp_loop_count := (tmp_ub - i) DIV tmp_step_size + 1;GOTO loop_label;

neg_step:IF i < tmp_ub THEN GOTO end_label;// the next statement uses i - tmp_ub// to evaluate tmp_loop_count to its correct, unsigned valuetmp_loop_count := (i - tmp_ub) DIV (-tmp_step_size) + 1;

loop_label:code for statement sequencetmp_loop_count := tmp_loop_count - 1;IF tmp_loop_count = 0 THEN GOTO end_label;i := i + tmp_step_size;GOTO loop_label;

end_label:

Figure 6.40 Code generation for a general for-statement.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

for (expr1; expr2; expr3) {body;

}

Figure 6.41 A for-loop in C.� �����������������������������������������������������������������������������������������������������������

SECTION 6.6 Conclusion 219

Page 220: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

expr1;while (expr2) {

body;expr3;

}

Figure 6.42 A while loop that is almost equivalent to the for-loop of Figure 6.41.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

FOR i := 1 TO n-3 STEP 4 DO// The first loop takes care of the indices 1 .. (n div 4) * 4sum := sum + a[i];sum := sum + a[i+1];sum := sum + a[i+2];sum := sum + a[i+3];

END FOR;

FOR i := (n div 4) * 4 + 1 TO n DO// This loop takes care of the remaining indicessum := sum + a[i];

END FOR;

Figure 6.43 Two for-loops resulting from unrolling a for-loop.� �����������������������������������������������������������������������������������������������������������

220 CHAPTER 6 Imperative and object-oriented programs

Page 221: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

parameter k

parameter 1

.

.

addresseshigh

dynamic link

registers & misc.

local variables

working stack

dynamic allocation

FP

partlow

addressesSP

return address

lexical pointer

Figure 6.44 An activation record with a dynamic allocation part.� �����������������������������������������������������������������������������������������������

SECTION 6.6 Conclusion 221

Page 222: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

of the calleeactivation record

activation recordof the caller

parameter n

.parameter 1

administration part

local variables

working stack

parameter k..

administration part

local variables

working stack

.

SP

FP

parameter 1

dynamic link

old FP

Figure 6.45 Two activation records on a stack.� �����������������������������������������������������������������������������������������������

222 CHAPTER 6 Imperative and object-oriented programs

Page 223: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

#include <setjmp.h>

jmp_buf jmpbuf; /* type defined in setjmp.h */

void handler(int signo) {printf("ERROR, signo = %d\n", signo);longjmp(jmpbuf, 1);

}

int main(void) {signal(6, handler); /* install the handler ... */signal(12, handler); /* ... for some signals */if (setjmp(jmpbuf) == 0) {

/* setting up the label for longjmp() lands here *//* normal code: */...

} else {/* returning from a call of longjmp() lands here *//* exception code: */...

}}

Figure 6.46 An example program using setjmp/longjmp in a signal handler.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

void init( *dst) { ... }

*alloc(void) { ... }

void dealloc( *arg) { ... }

void assign( *dst, *src) { ... }

bool compare( *tp1, *tp2) { ... }

tp

tp tp

tptp

tp

tp

Figure 6.47 A dope vector for generic type tp.� �����������������������������������������������������������������������������������������������

SECTION 6.6 Conclusion 223

Page 224: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

void A(int i) {showSP("A.SP.entry");if (i > 0) {B(i-1);}showSP("A.SP.exit");

}

void B(int i) {showSP("B.SP.entry");if (i > 0) {A(i-1);}showSP("B.SP.exit");

}

Figure 6.48 Mutually recursive test routines.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

void A(int i, void C()) {showSP("A.SP.entry");if (i > 0) {C(i-1, A);}showSP("A.SP.exit");

}

void B(int i, void C()) {showSP("B.SP.entry");if (i > 0) {C(i-1, B);}showSP("B.SP.exit");

}

Figure 6.49 Routines for testing routines as parameters.� �����������������������������������������������������������������������������������������������������������

224 CHAPTER 6 Imperative and object-oriented programs

Page 225: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

void A(int i, label L) {showSP("A.SP.entry");if (i > 0) {B(i-1, exit); return;}exit: showSP("A.SP.exit"); goto L;

}

void B(int i, label L) {showSP("B.SP.entry");if (i > 0) {A(i-1, exit); return;}exit: showSP("B.SP.exit"); goto L;

}

Figure 6.50 Routines for testing labels as parameters.� �����������������������������������������������������������������������������������������������������������

SECTION 6.6 Conclusion 225

Page 226: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

7�������������������������������������������������������������������������

Functional programs

226

Page 227: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

fac 0 = 1fac n = n * fac (n-1)

Figure 7.1 Functional specification of factorial in Haskell.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

int fac(int n) {int product = 1;

while (n > 0) {product *= n;n--;

}return product;

}

Figure 7.2 Imperative definition of factorial in C.� �����������������������������������������������������������������������������������������������������������

SECTION 7.3 Polymorphic type checking 227

Page 228: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

Compiler phase Language aspect

Lexical analyzer Offside rule

List notationList comprehensionParserPattern matching

Context handling Polymorphic type checking

Referential transparencyHigher-order functionsRun-time systemLazy evaluation

Figure 7.3 Overview of handling functional language aspects.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

7.5 Run-time systemC +

Functional core

High-level language

Code generation7.6

Desugaring7.4Type inference7.3

Optimizations 7.7

Figure 7.4 Structure of a functional compiler.� �����������������������������������������������������������������������������������������������

228 SECTION 7.5 Graph reduction

Page 229: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

fun p1,1 ... p1,n = expr1fun p2,1 ... p2,n = expr2...fun pm,1 ... pm,n = exprm

Figure 7.5 The general layout of a function using pattern matching.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

fun a1 ... an ⇒ if (cond1) then let defs1 in expr1else if (cond2) then let defs2 in expr2...else if (condm) then let defsm in exprm

else error "fun: no matching pattern"

Figure 7.6 Translation of the pattern-matching function of Figure 7.5.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

take a1 a2 = if (a1 == 0) thenlet xs = a2 in []

else if (a2 == []) thenlet n = a1 in []

else if (_type_constr a2 == Cons) thenlet

n = a1x = _type_field 1 a2xs = _type_field 2 a2

inx : take (n-1) xs

elseerror "take: no matching pattern"

Figure 7.7 Translation of the function take.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 7.5.2 The reduction engine 229

Page 230: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

take a1 a2 = if (a1 == 0) thenlet xs = a2 in []

else if (a2 == []) thenlet n = a1 in []

elselet

n = a1x = _type_field 1 a2xs = _type_field 2 a2

inx : take (n-1) xs

Figure 7.8 Optimized translation of the function take.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

last a1 = if (_type_constr a1 == Cons) thenlet

x = _type_field 1 a1xs = _type_field 2 a1

inif (xs == []) then

xelse

last xselse

error "last: no matching pattern"

Figure 7.9 Translation of the function last.� �����������������������������������������������������������������������������������������������������������

230 SECTION 7.5 Graph reduction

Page 231: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

T{ [ expr | ] } ⇒ [ expr ] (1)

T{ [ expr | F, Q ] } ⇒ if ( F ) then T{ [ expr | Q ] } (2)else []

T{ [ expr | e <- L, Q ] } ⇒ mappend fQ L (3)where

fQ e = T{ [ expr | Q ] }

Figure 7.10 Translation scheme for list comprehensions.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

sv_mul scal vec = lets_mul x = scal * x

inmap s_mul vec

Figure 7.11 A function returning a function.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

sv_mul_dot_s_mul scal x = scal * x

sv_mul scal vec = map (sv_mul_dot_s_mul scal) vec

Figure 7.12 The function of Figure 7.11, with s_mul lambda-lifted.� �����������������������������������������������������������������������������������������������������������

SECTION 7.6 Code generation for functional core programs 231

Page 232: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

en

e1

@

@

f

Figure 7.13 Identifying an essential redex.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

@

@*

@

3square

root:

Figure 7.14 A graph with a built-in operator with strict arguments.� �����������������������������������������������������������������������������������������������

232 SECTION 7.6 Code generation for functional core programs

Page 233: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

typedef enum {FUNC, NUM, NIL, CONS, APPL} node_type;

typedef struct node *Pnode;

typedef Pnode (*unary)(Pnode *arg);

struct function_descriptor {int arity;const char *name;unary code;

};

struct node {node_type tag;union {

struct function_descriptor func;int num;struct {Pnode hd; Pnode tl;} cons;struct {Pnode fun; Pnode arg;} appl;

} nd;};

/* Constructor functions */extern Pnode Func(int arity, const char *name, unary code);extern Pnode Num(int num);extern Pnode Nil(void);extern Pnode Cons(Pnode hd, Pnode tl);extern Pnode Appl(Pnode fun, Pnode arg);

Figure 7.15 Declaration of node types and constructor functions.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

Pnode Appl(const Pnode fun, Pnode arg) {Pnode node = (Pnode) heap_alloc(sizeof(*node));

node->tag = APPL;node->nd.appl.fun = fun;node->nd.appl.arg = arg;return node;

}

Figure 7.16 The node constructor function for application (@) nodes.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 7.6.1 Avoiding the construction of some application spines 233

Page 234: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

#include "node.h"#include "eval.h"

#define STACK_DEPTH 10000

static Pnode arg[STACK_DEPTH];static int top = STACK_DEPTH; /* grows down */

Pnode eval(Pnode root) {Pnode node = root;int frame, arity;

frame = top;for (;;) {

switch (node->tag) {case APPL: /* unwind */

arg[--top] = node->nd.appl.arg; /* stack argument */node = node->nd.appl.fun; /* application node */break;

case FUNC:arity = node->nd.func.arity;if (frame-top < arity) { /* curried function */

top = frame;return root;

}node = node->nd.func.code(&arg[top]); /* reduce */top += arity; /* unstack arguments */*root = *node; /* update root pointer */break;

default:return node;

}}

}

Figure 7.17 Reduction engine.� �����������������������������������������������������������������������������������������������������������

234 SECTION 7.7 Optimizing the functional core

Page 235: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

@root:

argument stack

@

twice square

3

Figure 7.18 Stacking the arguments while searching for a redex.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

Pnode mul(Pnode _arg0, Pnode _arg1) {Pnode a = eval(_arg0);Pnode b = eval(_arg1);

return Num(a->nd.num * b->nd.num);}

Pnode _mul(Pnode *arg) {return mul(arg[0], arg[1]);

}

struct node __mul = {FUNC, {2, "mul", _mul}};

Figure 7.19 Code and function descriptor of the built-in operator mul.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

argument stack

@

@

* @

square 3

Figure 7.20 A more complicated argument stack.� �����������������������������������������������������������������������������������������������

SUBSECTION 7.7.1 Strictness analysis 235

Page 236: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

Pnode conditional(Pnode _arg0, Pnode _arg1, Pnode _arg2) {Pnode cond = _arg0;Pnode _then = _arg1;Pnode _else = _arg2;

return eval(cond)->nd.num ? _then : _else;}

Pnode _conditional(Pnode *arg) {return conditional(arg[0], arg[1], arg[2]);

}

struct node __conditional ={FUNC, {3, "conditional", _conditional}};

Figure 7.21 Code and function descriptor of the built-in conditional operator.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

f a = letb = fac ac = b * b

inc + c

Figure 7.22 Example of a let-expression.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

Pnode f(Pnode _arg0) {Pnode a = _arg0;Pnode b = Appl(&__fac, a);Pnode c = Appl(Appl(&__mul, b), b);

return Appl(Appl(&__add, c), c);}

Figure 7.23 Translation of the let-expression of Figure 7.22.� �����������������������������������������������������������������������������������������������������������

236 SECTION 7.7 Optimizing the functional core

Page 237: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

Pnode average(Pnode _arg0, Pnode _arg1) {Pnode a = _arg0;Pnode b = _arg1;

returnAppl(

Appl(&__div,Appl(

Appl(&__add, a),b

)),Num(2)

);}

Figure 7.24 Translation of the function average.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

Pnode average(Pnode _arg0, Pnode _arg1) {Pnode a = _arg0;Pnode b = _arg1;

return div(Appl(Appl(&__add, a), b), Num(2));}

Figure 7.25 Suppressing the top-level spine in the translation of the function average.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

Pnode average(Pnode _arg0, Pnode _arg1) {Pnode a = _arg0;Pnode b = _arg1;

return div(add(a, b), Num(2));}

Figure 7.26 Suppressing the argument spine to div in Figure 7.25.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 7.7.1 Strictness analysis 237

Page 238: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

{b}

if

{}{b} {a,b}

= 0 /

a b

{a} {b}{b} {}

0b

Figure 7.27 Flow of strictness information in the AST of safe_div.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

Language construct Set to be propagated

L operator R L∪Rif C then T else E C∪(T∩E)

funm @ A 1 @ ... @ Ani=1

∪strict(fun, i)

min(m,n)

Ai

F @ A 1 @ ... @ An F

let v = V in E (E\{v})∪V , if v ∈ EE , otherwise

Figure 7.28 Rules for strictness information propagation.� �����������������������������������������������������������������������������������������������

238 SECTION 7.7 Optimizing the functional core

Page 239: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

if

{a,b}

{a} {b}

b=

{}{a}

a 0

{a,b}

@

{a} {b}

+@

f(+,+)

{a}

-

{a} {}

a 1

{b} {}

1b

Figure 7.29 Optimistic strictness analysis of the function f.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

Data definitions:1. Let Strict be an associative mapping from (identifier, int) pairs to Booleans,where each pair describes a function name and argument index.

Initializations:1. For each function f with arity m set Strict[ f, i] to true for arguments i rang-ing from 1 to m.

Inference rules:1. If propagation of strictness information through the AST of function fshows that f is not strict in argument i, then Strict[ f, i] must be false.

Figure 7.30 Closure algorithm for strictness predicate.� �����������������������������������������������������������������������������������������������

SUBSECTION 7.8.1 Variable-length nodes 239

Page 240: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

Pnode fac(Pnode _arg0) {Pnode n = _arg0;

return equal(n, Num(0))->nd.num ? Num(1): mul(n, fac(Appl(Appl(&__sub, n), Num(1))));

}

Figure 7.31 Lazy translation of the argument of fac.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

Pnode fac(Pnode _arg0) {Pnode n = _arg0;

return equal(n, Num(0))->nd.num ? Num(1): mul(n, fac(sub(n, Num(1))));

}

Figure 7.32 The first step in exploiting the strictness of the argument of fac.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

Pnode fac_evaluated(Pnode _arg0) {Pnode n = _arg0;

return equal_evaluated(n, Num(0))->nd.num ? Num(1): mul_evaluated(n, fac_evaluated(sub_evaluated(n, Num(1))));

}

Pnode fac(Pnode _arg0) {return fac_evaluated(eval(_arg0));

}

Figure 7.33 Exploiting the strictness of fac and the built-in operators.� �����������������������������������������������������������������������������������������������������������

240 CHAPTER 7 Functional programs

Page 241: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

int fac_unboxed(int n) {return (n == 0 ? 1 : n * fac_unboxed(n-1));

}

Pnode fac_evaluated(Pnode _arg0) {Pnode n = _arg0;

return Num(fac_unboxed(n->nd.num));}

Pnode fac(Pnode _arg0) {return fac_evaluated(eval(_arg0));

}

Figure 7.34 Strict, unboxed translation of the function fac.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

Pnode drop_unboxed(int n, Pnode lst) {if (n == 0) {

return lst;} else {

return drop_unboxed(n-1, tail(lst));}

}

Figure 7.35 Strict, unboxed translation of the function drop.� �����������������������������������������������������������������������������������������������������������

SECTION 7.9 Conclusion 241

Page 242: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

Pnode drop_unboxed(int n, Pnode lst) {L_drop_unboxed:

if (n == 0) {return lst;

} else {int _tmp0 = n-1;Pnode _tmp1 = tail(lst);

n = _tmp0; lst = _tmp1;goto L_drop_unboxed;

}}

Figure 7.36 Translation of drop with tail recursion eliminated.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

fac n = if (n == 0) then 1 else prod n (n-1)where

prod acc n = if (n == 0) then accelse prod (acc*n) (n-1)

Figure 7.37 Tail-recursive fac with accumulating argument.� �����������������������������������������������������������������������������������������������������������

242 CHAPTER 7 Functional programs

Page 243: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

int fac_dot_prod_unboxed(int acc, int n) {L_fac_dot_prod_unboxed:

if (n == 0) {return acc;

} else {int _tmp0 = n * acc;int _tmp1 = n-1;

acc = _tmp0; n = _tmp1;goto L_fac_dot_prod_unboxed;

}}

int fac_unboxed(int n) {if (n == 0) {

return 1;} else {

return fac_dot_prod_unboxed(n, n-1);}

}

Figure 7.38 Accumulating translation of fac, with tail recursion elimination.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

F x1...xn = if B then V else E ⊕ F E 1 ...En

⇒F x1...xn = if B then V else F ′ E E 1 ...En

F ′ xacc x1...xn = if B then xacc ⊕ V else F ′ (xacc ⊕ E) E 1 ...En

Figure 7.39 Accumulating argument translation scheme.� �����������������������������������������������������������������������������������������������������������

SECTION 7.9 Conclusion 243

Page 244: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

8�������������������������������������������������������������������������

Logic programs

244

Page 245: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

goal AND goal AND

goal AND goal AND

goal AND goal AND

OR

OR

...

OR

...

...

... AND goal top element

bottom element

Figure 8.1 The goal list stack.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

[ first goal ?= clause head ], clause body, other goals.first goal, other goals.

clause head :- clause body.

Figure 8.2 The action of ‘Attach clauses’ using one clause.� �����������������������������������������������������������������������������������������������

SECTION 8.3 Unification 245

Page 246: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

struct variable {char *name;struct term *term;

};

struct structure {char *functor;int arity;struct term **components;

};

typedef enum {Is_Constant, Is_Variable, Is_Structure} Term_Type;typedef struct term {

Term_Type type;union {

char *constant; /* Is_Constant */struct variable variable; /* Is_Variable */struct structure structure; /* Is_Structure */

} term;} Term;

Figure 8.3 Data types for the construction of terms.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

int unify_terms(Term *goal_arg, Term *head_arg) {/* Handle any bound variables: */Term *goal = deref(goal_arg);Term *head = deref(head_arg);

if (goal->type == Is_Variable || head->type == Is_Variable) {return unify_unbound_variable(goal, head);

}else {

return unify_non_variables(goal, head);}

}

Figure 8.4 C code for the unification of two terms.� �����������������������������������������������������������������������������������������������������������

246 SECTION 8.4 The general implementation model, compiled

Page 247: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

Term *deref(Term *t) {while (t->type == Is_Variable && t->term.variable.term != 0) {

t = t->term.variable.term;}return t;

}

Figure 8.5 The function deref().� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

int unify_unbound_variable(Term *goal, Term *head) {/* Handle identical variables: */if (goal == head) {

/* Unification of identical variables is trivial */}else {

/* Bind the unbound variable to the other term: */if (head->type == Is_Variable) {

trail_binding(head);head->term.variable.term = goal;

}else {

trail_binding(goal);goal->term.variable.term = head;

}}return 1; /* variable unification always succeeds */

}

Figure 8.6 C code for unification involving at least one unbound variable.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 8.4.2 Compiled clause search and unification 247

Page 248: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

int unify_non_variables(Term *goal, Term *head) {/* Handle terms of different type: */if (goal->type != head->type) return 0;

switch (goal->type) {case Is_Constant: /* both are constants */

return unify_constants(goal, head);case Is_Structure: /* both are structures */

return unify_structures(&goal->term.structure, &head->term.structure

);}

}

Figure 8.7 C code for the unification of two non-variables.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

int unify_constants(Term *goal, Term *head) {return strcmp(goal->term.constant, head->term.constant) == 0;

}

Figure 8.8 C code for the unification of two constants.� �����������������������������������������������������������������������������������������������������������

248 SECTION 8.4 The general implementation model, compiled

Page 249: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

int unify_structures(struct structure *s_goal, struct structure *s_head

) {int counter;

if (s_goal->arity != s_head->arity|| strcmp(s_goal->functor, s_head->functor) != 0) return 0;

for (counter = 0; counter < s_head->arity; counter++) {if (!unify_terms(

s_goal->components[counter], s_head->components[counter])) return 0;

}

return 1;}

Figure 8.9 C code for the unification of two structures.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

E

C

B

(a) (b)

A A

BD C E

D

Figure 8.10 Examples of variable–variable bindings.� �����������������������������������������������������������������������������������������������

SUBSECTION 8.4.3 Optimized clause selection in the WAM 249

Page 250: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

(a)

V

W

X

(b)

A

Z

A

Z

BD C E BD C E

Figure 8.11 Examples of more complicated variable–variable bindings.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

void number_pair_list(void (*Action)(int v1, int v2)) {(*Action)(1, 3);(*Action)(4, 6);(*Action)(7, 3);

}

Figure 8.12 An example of a list procedure.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

int fs_sum;

void fs_test_sum(int v1, int v2) {if (v1 + v2 == fs_sum) {

printf("Solution found: %d, %d\n", v1, v2);}

}

void find_sum(int sum) {fs_sum = sum;number_pair_list(fs_test_sum);

}

Figure 8.13 An application of the list procedure.� �����������������������������������������������������������������������������������������������������������

250 SECTION 8.4 The general implementation model, compiled

Page 251: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

void find_sum(int sum) {void test_sum(int v1, int v2) {

if (v1 + v2 == sum) {printf("Solution found: %d, %d\n", v1, v2);

}}

number_pair_list(test_sum);}

Figure 8.14 An application of the list procedure, using nested routines.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

void parent_2(Term *goal_arg1,Term *goal_arg2,Action goal_list_tail

) {

... /* the local routines parent_2_clause_[1-5]() */

/* OR of all clauses for parent/2 */parent_2_clause_1(); /* parent(arne, james). */parent_2_clause_2(); /* parent(arne, sachiko). */parent_2_clause_3(); /* parent(koos, rivka). */parent_2_clause_4(); /* parent(sachiko, rivka). */parent_2_clause_5(); /* parent(truitje, koos). */

}

Figure 8.15 Translation of the relation parent/2.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 8.4.5 Implementing the predicates assert and retract 251

Page 252: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

/* translation of ’parent(arne, sachiko).’ */void parent_2_clause_2(void) {

/* translation of ’arne, sachiko).’ */void parent_2_clause_2_arg_1(void) {

/* translation of ’sachiko).’ */void parent_2_clause_2_arg_2(void) {

/* translation of ’.’ */void parent_2_clause_2_body(void) {

goal_list_tail();}

/* translation of head term ’sachiko)’ */unify_terms(goal_arg2, put_constant("sachiko"),

parent_2_clause_2_body);

}

/* translation of head term ’arne, ’ */unify_terms(goal_arg1, put_constant("arne"),

parent_2_clause_2_arg_2);

}

/* translation of ’parent(’ */parent_2_clause_2_arg_1();

}

Figure 8.16 Generated clause routine for parent(arne, sachiko).� �����������������������������������������������������������������������������������������������������������

252 SECTION 8.4 The general implementation model, compiled

Page 253: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

void unify_unbound_variable(Term *goal_arg, Term *head_arg, Action goal_list_tail

) {if (goal_arg == head_arg) {

/* Unification of identical variables succeeds trivially */goal_list_tail();

}else {

/* Bind the unbound variable to the other term: */if (head_arg->type == Is_Variable) {

head_arg->term.variable.term = goal_arg;goal_list_tail();head_arg->term.variable.term = 0;

}else {

goal_arg->term.variable.term = head_arg;goal_list_tail();goal_arg->term.variable.term = 0;

}}

}

Figure 8.17 C code for full backtracking variable unification.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

void query(void) {Term *X = put_variable("X");

void display_X(void) {print_term(X);printf("\n");

}

parent_2(put_constant("arne"), X, display_X);}

Figure 8.18 Possible generated code for the query ?− parent(arne, X).� �����������������������������������������������������������������������������������������������������������

SECTION 8.5 Compiled code for unification 253

Page 254: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

void grandparent_2(Term *goal_arg1, Term *goal_arg2, Action goal_list_tail

) {/* translation of ’grandparent(X,Z):-parent(X,Y),parent(Y,Z).’ */void grandparent_2_clause_1(void) {

/* translation of ’X,Z):-parent(X,Y),parent(Y,Z).’ */void grandparent_2_clause_1_arg_1(void) {

Term *X = put_variable("X");

/* translation of ’Z):-parent(X,Y),parent(Y,Z).’ */void grandparent_2_clause_1_arg_2(void) {

Term *Z = put_variable("Z");

/* translation of body ’parent(X,Y),parent(Y,Z).’ */void grandparent_2_clause_1_body(void) {

Term *Y = put_variable("Y");

/* translation of ’parent(Y,Z).’ */void grandparent_2_clause_1_goal_2(void) {

parent_2(Y, goal_arg2, goal_list_tail);}

/* translation of ’parent(X,Y),’ */parent_2(goal_arg1, Y, grandparent_2_clause_1_goal_2);

}

/* translation of head term ’Z):-’ */unify_terms(goal_arg2, Z, grandparent_2_clause_1_body);

}

/* translation of head term ’X,’ */unify_terms(goal_arg1, X, grandparent_2_clause_1_arg_2);

}

/* translation of ’grandparent(’ */grandparent_2_clause_1_arg_1();

}

/* OR of all clauses for grandparent/2 */grandparent_2_clause_1();

}

Figure 8.19 Clause routine generated for grandparent/2.� �����������������������������������������������������������������������������������������������������������

254 SECTION 8.5 Compiled code for unification

Page 255: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

void parent_2(Term *goal_arg1,Term *goal_arg2,Action goal_list_tail

) {

... /* the local routines parent_2_clause_[1-5]() */

/* switch_on_term(L_Variable, L_Constant, L_Structure) */switch (deref(goal_arg1)->type) {case Is_Variable: goto L_Variable;case Is_Constant: goto L_Constant;case Is_Structure: goto L_Structure;}

... /* code labeled by L_Variable, L_Constant, L_Structure */

L_fail:;}

Figure 8.20 Optimized translation of the relation parent/2.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

L_Variable:/* OR of all clauses for parent/2 */parent_2_clause_1(); /* parent(arne, james). */parent_2_clause_2(); /* parent(arne, sachiko). */parent_2_clause_3(); /* parent(koos, rivka). */parent_2_clause_4(); /* parent(sachiko, rivka). */parent_2_clause_5(); /* parent(truitje, koos). */goto L_fail;

Figure 8.21 Code generated for the label L_Variable.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 8.5.1 Unification instructions in the WAM 255

Page 256: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

L_Constant:/* switch_on_constant(8, constant_table) */switch (

entry(deref(goal_arg1)->term.constant, 8, constant_table)) {case ENTRY_arne: goto L_Constant_arne;case ENTRY_koos: goto L_Constant_koos;case ENTRY_sachiko: goto L_Constant_sachiko;case ENTRY_truitje: goto L_Constant_truitje;}goto L_fail;

L_Constant_arne:parent_2_clause_1(); /* parent(arne, james). */parent_2_clause_2(); /* parent(arne, sachiko). */goto L_fail;

L_Constant_koos:parent_2_clause_3(); /* parent(koos, rivka). */goto L_fail;

L_Constant_sachiko:parent_2_clause_4(); /* parent(sachiko, rivka). */goto L_fail;

L_Constant_truitje:parent_2_clause_5(); /* parent(truitje, koos). */goto L_fail;

Figure 8.22 Code generated for the labels L_Constant_....� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

L_Structure:goto L_fail;

Figure 8.23 Code generated for the label L_Structure.� �����������������������������������������������������������������������������������������������������������

256 SECTION 8.5 Compiled code for unification

Page 257: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

void first_gp_2(Term *goal_arg1, Term *goal_arg2, Action goal_list_tail

) {/* label declarations required by GNU C for non-local jump */__label__ L_cut;

/* translation of ’first_gp(X,Z):-parent(X,Y),!,parent(Y,Z).’ */void first_gp_2_clause_1(void) {

/* translation of ’X,Z):-parent(X,Y),!,parent(Y,Z).’ */void first_gp_2_clause_1_arg_1(void) {

Term *X = put_variable("X");/* translation of ’Z):-parent(X,Y),!,parent(Y,Z).’ */void first_gp_2_clause_1_arg_2(void) {

Term *Z = put_variable("Z");/* translation of body ’parent(X,Y),!,parent(Y,Z).’ */void first_gp_2_clause_1_body(void) {

Term *Y = put_variable("Y");/* translation of ’!,parent(Y,Z).’ */void first_gp_2_clause_1_goal_2(void) {

/* translation of ’parent(Y,Z).’ */void first_gp_2_clause_1_goal_3(void) {

parent_2(Y, goal_arg2, goal_list_tail);}/* translation of ’!,’ */first_gp_2_clause_1_goal_3();

goto L_cut;}/* translation of ’parent(X,Y),’ */parent_2(goal_arg1, Y, first_gp_2_clause_1_goal_2);

}/* translation of head term ’Z):-’ */unify_terms(goal_arg2, Z, first_gp_2_clause_1_body);

}/* translation of head term ’X,’ */unify_terms(goal_arg1, X, first_gp_2_clause_1_arg_2);

}/* translation of ’first_gp(’ */first_gp_2_clause_1_arg_1();

}/* OR of all clauses for first_gp/2 */first_gp_2_clause_1();

L_fail:;L_cut:;}

Figure 8.24 Clause routine generated for first_grandparent/2.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 8.5.2 Deriving a unification instruction by manual partial evaluation 257

Page 258: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

void parent_2(Term *goal_arg1,Term *goal_arg2,Action goal_list_tail

) {

... /* the local routines parent_2_clause_[1-5]() */

/* guarded OR of all clauses for parent/2 */if (!retracted_parent_2_clause_1)

parent_2_clause_1(); /* parent(arne, james). */if (!retracted_parent_2_clause_2)

parent_2_clause_2(); /* parent(arne, sachiko). */if (!retracted_parent_2_clause_3)

parent_2_clause_3(); /* parent(koos, rivka). */if (!retracted_parent_2_clause_4)

parent_2_clause_4(); /* parent(sachiko, rivka). */if (!retracted_parent_2_clause_5)

parent_2_clause_5(); /* parent(truitje, koos). */L_fail:

if (number_of_clauses_added_at_end_for_parent_2 > 0) {stack_argument(goal_arg2);stack_argument(goal_arg1);stack_argument(put_constant("parent/2"));interpret(goal_list_tail);

}L_cut:;}

Figure 8.25 Translation of parent/2 with code for controlling asserted and retracted clauses.� �����������������������������������������������������������������������������������������������������������

258 SECTION 8.5 Compiled code for unification

Page 259: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

...

...stack_argument(goal_arg2);stack_argument(goal_arg1);stack_argument(put_constant(...interpret(goal_list_tail);.........

...

Compiled code

stack

Interpreter

top

data

...

...

...

...

void interpret(...

codecontrol

Figure 8.26 Switch to interpretation of added clauses.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

void do_relation(const char *relation, Action goal_list_tail) {switch (entry(relation, N, relation_table)) {case ENTRY_...:case ENTRY_parent_2:

goal_arg1 = unstack_argument();goal_arg2 = unstack_argument();parent_2(goal_arg1, goal_arg2, goal_list_tail);break;

case ENTRY_grandparent_2:...break;

case ENTRY_...:...default:

interpret_asserted_relation(relation, goal_list_tail);break;

}}

Figure 8.27 Dispatch routine for goals in asserted clauses.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 8.5.2 Deriving a unification instruction by manual partial evaluation 259

Page 260: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

stack top

Interpreter

...

...

code

goal_arg1 = unstack_argument();goal_arg2 = unstack_argument();

Compiled code

...

...data

...

...parent_2(goal_arg1, goal_arg2, goal_list_tail);

...

...

...void parent_2(...

control

...

Figure 8.28 Switch to execution of compiled clauses.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

/* translation of ’parent(arne, sachiko).’ */void parent_2_clause_2(void) {

Trail_Mark trail_mark;

set_trail_mark(&trail_mark);/* translation of ’(arne, sachiko)’ */if (unify_terms(goal_arg1, put_constant("arne"))&& unify_terms(goal_arg2, put_constant("sachiko"))) {

/* translation of ’.’ */void parent_2_clause_2_body(void) {

goal_list_tail();}

/* translation of ’.’ */parent_2_clause_2_body();

}restore_bindings_until_trail_mark(&trail_mark);

}

Figure 8.29 Clause routine with flat unification for parent(arne, sachiko).� �����������������������������������������������������������������������������������������������������������

260 SECTION 8.5 Compiled code for unification

Page 261: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

/* optimized translation of ’parent(arne, sachiko).’ */void parent_2_clause_2(void) {

Trail_Mark trail_mark;

set_trail_mark(&trail_mark);/* optimized translation of ’(arne, sachiko)’ */UNIFY_CONSTANT(goal_arg1, "arne"); /* macro */UNIFY_CONSTANT(goal_arg2, "sachiko"); /* macro */

/* optimized translation of ’.’ */goal_list_tail();

L_fail:restore_bindings_until_trail_mark(&trail_mark);

}

Figure 8.30 Clause routine with compiled unification for parent(arne, sachiko).� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

g = deref(goal_arg);if (g->type == Is_Variable) {

trail_binding(g);g->term.variable.term = put_constant(head_text);

}else {

if (g->type != Is_Constant) goto L_fail;if (strcmp(g->term.constant, head_text) != 0) goto L_fail;

}

Figure 8.31 The unification instruction UNIFY_CONSTANT.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 8.5.3 Unification of structures in the WAM 261

Page 262: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

v = deref(head_var); /* head_var may already be bound */g = deref(goal_arg);if (v->type == Is_Variable) {

if (g != v) {trail_binding(v);v->term.variable.term = g;

}}else {

/* no further compilation possible *//* call interpreter */if (!unify_terms(g, v)) goto L_fail;

}

Figure 8.32 The unification instruction UNIFY_VARIABLE.� �����������������������������������������������������������������������������������������������������������

262 SECTION 8.5 Compiled code for unification

Page 263: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

int unify_terms(Term *goal_arg, Term *head_arg) {/* Handle any bound variables: */Term *goal = deref(goal_arg);Term *head = deref(head_arg);

if (goal->type == Is_Variable || head->type == Is_Variable) {/* Handle identical variables: */if (goal == head) return 1;

/* Bind the unbound variable to the other term: */if (head->type == Is_Variable) {

trail_binding(head);head->term.variable.term = goal;

}else {

trail_binding(goal);goal->term.variable.term = head;

}return 1; /* always succeeds */

}else {

/* Handle terms of different type: */if (goal->type != head->type) return 0;

switch (goal->type) {case Is_Constant: /* both are constants */

return strcmp(goal->term.constant, head->term.constant) == 0;case Is_Structure: /* both are structures */

return unify_structures(&goal->term.structure, &head->term.structure

);}

}}

Figure 8.33 Deriving the instruction UNIFY_CONSTANT, stage 1.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 8.5.4 An optimization: read/write mode 263

Page 264: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

int unify_constant(Term *goal_arg, char *head_text) {Term *goal;

/* Handle bound goal_arg: */goal = deref(goal_arg);

if (goal->type == Is_Variable|| (put_constant(head_text))->type == Is_Variable) {

/* Handle identical variables: */if (goal == (put_constant(head_text))) return 1;

/* Bind the unbound variable to the other term: */if ((put_constant(head_text))->type == Is_Variable) {

trail_binding((put_constant(head_text)));(put_constant(head_text))->term.variable.term = goal;

}else {

trail_binding(goal);goal->term.variable.term = (put_constant(head_text));

}return 1; /* always succeeds */

}else {

/* Handle terms of different type: */if (goal->type != (put_constant(head_text))->type) return 0;

switch (goal->type) {case Is_Constant: /* both are constants */

returnstrcmp(

goal->term.constant,(put_constant(head_text))->term.constant

) == 0;case Is_Structure: /* both are structures */

return unify_structures(&goal->term.structure,&(put_constant(head_text))->term.structure

);}

}}

Figure 8.34 Deriving the instruction UNIFY_CONSTANT, stage 2.� �����������������������������������������������������������������������������������������������������������

264 SECTION 8.5 Compiled code for unification

Page 265: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

int unify_constant(Term *goal_arg, char *head_text) {Term *goal;

/* Handle bound goal_arg: */goal = deref(goal_arg);

if (goal->type == Is_Variable || Is_Constant == Is_Variable) {/* Handle identical variables: */if (goal == (put_constant(head_text))) return 1;

/* Bind the unbound variable to the other term: */if (Is_Constant == Is_Variable) {

trail_binding((put_constant(head_text)));ERRONEOUS = goal;

}else {

trail_binding(goal);goal->term.variable.term = (put_constant(head_text));

}return 1; /* always succeeds */

}else {

/* Handle terms of different type: */if (goal->type != Is_Constant) return 0;

switch (goal->type) {case Is_Constant: /* both are constants */

return strcmp(goal->term.constant, head_text) == 0;case Is_Structure: /* both are structures */

return unify_structures(&goal->term.structure, ERRONEOUS

);}

}}

Figure 8.35 Deriving the instruction UNIFY_CONSTANT, stage 3.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 8.5.4 An optimization: read/write mode 265

Page 266: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

int unify_constant(Term *goal_arg, char *head_text) {Term *goal;

/* Handle bound goal_arg: */goal = deref(goal_arg);

if (goal->type == Is_Variable || 0) {/* Handle identical variables: */if (0) return 1;

/* Bind the unbound variable to the other term: */if (0) {

trail_binding((put_constant(head_text)));ERRONEOUS = goal;

}else {

trail_binding(goal);goal->term.variable.term = (put_constant(head_text));

}return 1; /* always succeeds */

}else {

/* Handle terms of different type: */if (goal->type != Is_Constant) return 0;

switch (Is_Constant) {case Is_Constant: /* both are constants */

return strcmp(goal->term.constant, head_text) == 0;case Is_Structure: /* both are structures */

return unify_structures(&goal->term.structure, ERRONEOUS

);}

}}

Figure 8.36 Deriving the instruction UNIFY_CONSTANT, stage 4.� �����������������������������������������������������������������������������������������������������������

266 SECTION 8.5 Compiled code for unification

Page 267: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

int unify_constant(Term *goal_arg, char *head_text) {Term *goal;

/* Handle bound goal_arg: */goal = deref(goal_arg);

if (goal->type == Is_Variable) {trail_binding(goal);goal->term.variable.term = (put_constant(head_text));return 1; /* always succeeds */

}else {

if (goal->type != Is_Constant) return 0;return strcmp(goal->term.constant, head_text) == 0;

}}

Figure 8.37 Deriving the instruction UNIFY_CONSTANT, stage 5.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

int unify_constant(Term *goal_arg, char *head_text) {Term *goal;

goal = deref(goal_arg);if (goal->type == Is_Variable) {

trail_binding(goal);goal->term.variable.term = put_constant(head_text);

}else {

if (goal->type != Is_Constant) goto L_fail;if (strcmp(goal->term.constant, head_text) != 0) goto L_fail;

}return 1;

L_fail:return 0;

}

Figure 8.38 Deriving the instruction UNIFY_CONSTANT, final result.� �����������������������������������������������������������������������������������������������������������

SUBSECTION 8.5.4 An optimization: read/write mode 267

Page 268: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

g = deref(goal_arg);if (g->type == Is_Variable) {

trail_binding(g);g->term.variable.term =

put_structure(head_functor, head_arity);initialize_components(g->term.variable.term);

}else {

if (g->type != Is_Structure) goto L_fail;if (g->term.structure.arity != head_arity|| strcmp(g->term.structure.functor, head_functor) != 0) goto L_fail;

}

Figure 8.39 The unification instruction UNIFY_STRUCTURE.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

/* match times(2, X) */UNIFY_STRUCTURE(goal_arg, "times", 2); /* macro */{ /* match (2, X) */

Term **goal_comp = deref(goal_arg)->term.structure.components;

UNIFY_CONSTANT(goal_comp[0], "2"); /* macro */UNIFY_VARIABLE(goal_comp[1], X); /* macro */

}

Figure 8.40 Compiled code for the head times(2, X).� �����������������������������������������������������������������������������������������������������������

268 SECTION 8.5 Compiled code for unification

Page 269: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

goal:

variablestructure

"times"

2components

_A01

_A02

0

0

Y

variablesanonymous

Figure 8.41 The effect of the instruction UNIFY_STRUCTURE.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

goal:

variablestructure

"times"

2components

_A01

Y

_A02

constant

2

variable

X . . .

anonymousvariables

Figure 8.42 The effect of the instructions of Figure 8.40.� �����������������������������������������������������������������������������������������������

SUBSECTION 8.5.6 Conclusion 269

Page 270: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

/* match times(2, X) */mode_1 = mode; /* save mode */UNIFY_STRUCTURE(&goal_arg, "times", 2); /* macro */

/* saves read/write mode and may set it to Write_Mode */{ /* match (2, X) */

register Term **goal_comp =deref(goal_arg)->term.structure.components;

UNIFY_CONSTANT(&goal_comp[0], "2"); /* macro */UNIFY_VARIABLE(&goal_comp[1], X); /* macro */

}mode = mode_1;

Figure 8.43 Compiled code with read/write mode for the head times(2, X).� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

if (mode == Read_Mode) {g = deref(*goal_ptr);if (g->type == Is_Variable) {

trail_binding(g);g->term.variable.term = put_constant(head_text);

}else {

if (g->type != Is_Constant) goto L_fail;if (strcmp(g->term.constant, head_text) != 0) goto L_fail;

}}else { /* mode == Write_Mode */

*goal_ptr = put_constant(head_text);}

Figure 8.44 The instruction UNIFY_CONSTANT with read/write mode.� �����������������������������������������������������������������������������������������������������������

270 SECTION 8.5 Compiled code for unification

Page 271: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

if (mode == Read_Mode) {g = deref(*goal_ptr);if (g->type == Is_Variable) {

trail_binding(g);g->term.variable.term =

put_structure(head_functor, head_arity);mode = Write_Mode; /* signal uninitialized goals */

}else {

if (g->type != Is_Structure) goto L_fail;if (g->term.structure.arity != head_arity|| strcmp(g->term.structure.functor, head_functor) != 0) goto L_fail;

}}else { /* mode == Write_Mode */

*goal_ptr = put_structure(head_functor, head_arity);}

Figure 8.45 The instruction UNIFY_STRUCTURE with read/write mode.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

goal:

variablestructure

"times"

2components

Y

???

???

Figure 8.46 The effect of the instruction UNIFY_STRUCT with read/write mode.� �����������������������������������������������������������������������������������������������

SUBSECTION 8.5.6 Conclusion 271

Page 272: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

goal:

variablestructure

"times"

2components

Y

. . .X

constant

2

variable

Figure 8.47 The effect of the instructions of Figure 8.40 with read/write mode.� �����������������������������������������������������������������������������������������������

272 SECTION 8.5 Compiled code for unification

Page 273: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

9�������������������������������������������������������������������������

Parallel and distributedprograms

273

Page 274: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

CPU CPU CPU

CPU CPU CPU

mem mem mem

shared memory

(a) multiprocessor

(b) multicomputer

network

Figure 9.1 Multiprocessors and multicomputers.� �����������������������������������������������������������������������������������������������

274 SECTION 9.4 Message passing

Page 275: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

monitor BinMonitor;bin: integer;occupied: Boolean := false;full, empty: Condition;

operation put(x: integer);begin

while occupied do # wait if the bin already is occupiedwait(empty);

od;bin := x; # put the item in the binoccupied := true;signal(full); # wake up a process blocked in get

end;

operation get(x: out integer);begin

while not occupied do # wait if the bin is emptywait(full);

od;x := bin; # get the item from the binoccupied := false;signal(empty); # wakeup a process blocked in put

end;end;

Figure 9.2 An example monitor.� �����������������������������������������������������������������������������������������������������������

SECTION 9.8 Conclusion 275

Page 276: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

array, part 2

array, part 1

data-parallel

pr. 2

pr. 1

process 1

process 2

shared variables

shared variables

read

read

write

write

parallel objects

obj.

process 1 obj.

process 2

process 1

process 2

Tuple Space

Tuple Space

OUT

OUT

IN

IN

msg msg

process 1

process 2

message passing

receivesend

sendreceive

Figure 9.3 Summary of the five parallel programming models.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

Status

Program counter

Stack pointer

Stack limits

Registers

Next-pointer

Figure 9.4 Structure of a thread control block.� �����������������������������������������������������������������������������������������������

276 CHAPTER 9 Parallel and distributed programs

Page 277: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

not runnable

not runnable

not runnable

runnable

lock variable

(a)

(c)

(b)

Thread control blocks

Thread control blocks

Figure 9.5 A lock variable containing a list of blocked threads.� �����������������������������������������������������������������������������������������������

SECTION 9.8 Conclusion 277

Page 278: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

marshaling

unmarshaling

name

age

"John"

h n \0

4-byte length

00 00 00 09 J o 00 00 00 1A

0000001A

"John"

= 26

1A000000

age

= 26

name

Figure 9.6 Marshaling.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

40007addressCPU

Determine_Value,

7, 4000,

"Diamond"

CPU 4 CPU 7

address 4000:Y:

X:

Figure 9.7 Using object identifiers for remote references.� �����������������������������������������������������������������������������������������������

278 CHAPTER 9 Parallel and distributed programs

Page 279: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

reference to XX:

reference to X

X:

X:reference to X

machine C

(a)

machine Bmachine A

(c)

(b)forwarding

address

Figure 9.8 Pointer chasing.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

int n, year;float f;

... /* code initializing n and f */

(1) in("Olympic year", 1928);(2) in("Classic movie", "Way out West", 1937);(3) in("Classic movie", "Sons of the desert", 1933);(4) in("Classic movie", "Sons of the desert", ? &year);(5) in("Popular number", 65536);(6) in("Popular number", 3.14159);(7) in("Popular number", n);(8) in("Popular number", f);

Figure 9.9 A demo program in C/Linda.� �����������������������������������������������������������������������������������������������������������

SECTION 9.8 Conclusion 279

Page 280: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

Partition 1:(1) in("Olympic year", 1928);

Partition 2:(2) in("Classic movie", "Way out West", 1937);

Partition 3:(3) in("Classic movie", "Sons of the desert", 1933);(4) in("Classic movie", "Sons of the desert", ? &year);

Partition 4:(5) in("Popular number", 65536);(7) in("Popular number", n);

Partition 5:(6) in("Popular number", 3.14159);(8) in("Popular number", f);

Figure 9.10 The partitions for the demo C/Linda program in Figure 9.9.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

1

5051

100

451

500

1 1000

CPU 0

CPU 1

CPU 10

Figure 9.11 An array distributed over 10 CPUs.� �����������������������������������������������������������������������������������������������

280 CHAPTER 9 Parallel and distributed programs

Page 281: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

INPUT:ID: number of this processor (ranging from 0 to P-1)lower_bound: number of first row assigned to this processorupper_bound: number of last row assigned to this processor

real A[lower_bound..upper_bound, 1000],B[lower_bound-1 .. upper_bound+1, 1000];

if ID > 0 then send B[lower_bound, *] to processor ID-1;if ID < P-1 then send B[upper_bound, *] to processor ID+1;if ID > 0 then receive B[lower_bound-1, *] from processor ID-1;if ID < P-1 then receive B[upper_bound+1, *] from processor ID+1;for i := lower_bound to upper_bound do

for j := 1 to 1000 doA[i, j] := B[i-1, j] + B[i+1, j];

od;od;

Figure 9.12 Generated (pseudo-)code.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

int Maximum(int value) {if (mycpu == 1) {

/* the first CPU creates the tuple */out("max", value, 1);

} else {/* other CPUs wait their turn */in("max", ? &max, mycpu);if (value > max) max = value;out("max", max, mycpu + 1);

}/* wait until all CPUs are done */read("max", ? &max, P);return max;

}

Figure 9.13 C/Linda code for the operation Maximum.� �����������������������������������������������������������������������������������������������������������

SECTION 9.8 Conclusion 281

Page 282: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

Appendix A − A simple object-oriented compiler/interpreter

282

Page 283: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

declarations simpleexpressions

assignments for-loops

� �������������������������������������������������������������������������������������������������������������������������������������������������

lexical analysis lexical analysisof declarations

parsing parsing ofsimpleexpressions

context handling context handlingof declarations

optimization optimization offor-loops

code generation code generationfor assignments

���������������������

Figure A.1 Table of tasks in a compiler with some tasks filled in.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

expression → digit | parenthesized_expressiondigit → DIGITparenthesized_expression → ’(’ expression operator expression ’)’operator → ’+’ | ’*’

Figure A.2 The grammar for simple fully parenthesized expressions in AND/OR form.� �����������������������������������������������������������������������������������������������������������

SECTION A.4 Evaluation 283

Page 284: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

class Demo_Compiler {public static void main(String[] args) {

// Get the intermediate codeLex.Get_Token(); // start the lexical analyserExpression icode = Expression.Parse_Or();if (Lex.Token_Class != Lex.EOF) {

System.err.println("Garbage at end of program ignored");}if (icode == null) {

System.err.println("No intermediate code produced");return;

}

// Print itSystem.out.print("Expression: ");icode.Print();System.out.println();

// Interpret itSystem.out.print("Interpreted: ");System.out.println(icode.Interpret());

// Generate code for itSystem.out.println("Code:");icode.Generate_Code();System.out.println("PRINT");

}}

Figure A.3 Class Demo_Compiler, driver for the object-oriented demo compiler.� �����������������������������������������������������������������������������������������������������������

284 Appendix A − A simple object-oriented compiler/interpreter

Page 285: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

import java.io.IOException;

class Lex {public static int Token_Class;public static final int EOF = 256;public static final int DIGIT = 257;public static char Token_Char_Value;

public static void Get_Token() {char ch;

// Get non-whitespace characterdo {int ch_or_EOF;

try {ch_or_EOF = System.in.read();}catch (IOException ex) {ch_or_EOF = -1;}if (ch_or_EOF < 0) {Token_Class = EOF; return;}ch = (char)ch_or_EOF; // cast is safe

} while (Character.isWhitespace(ch));

// Classify itif (Character.isDigit(ch)) {

Token_Class = DIGIT; Token_Char_Value = ch;}else {

Token_Class = ch;}

}}

Figure A.4 Class Lex, lexical analyzer for the object-oriented demo compiler.� �����������������������������������������������������������������������������������������������������������

SECTION A.4 Evaluation 285

Page 286: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

abstract class Expression {public static Expression Parse_Or() {

// Try to parse a parenthesized_expressionParenthesized_Expression pe = new Parenthesized_Expression();if (pe.Parse_And()) return pe;

// Try to parse a digitDigit d = new Digit();if (d.Parse_And()) return d;

return null;}

abstract public void Print();abstract public int Interpret();abstract public void Generate_Code();

}

Figure A.5 Class Expression for the object-oriented demo compiler.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

class Digit extends Expression {private char digit = ’\0’;

public boolean Parse_And() {if (Lex.Token_Class == Lex.DIGIT) {

digit = Lex.Token_Char_Value;Lex.Get_Token();return true;

}return false;

}

public void Print() {System.out.print(digit);}

public int Interpret() {return digit - ’0’;}

public void Generate_Code() {System.out.print("PUSH " + digit + "\n");

}}

Figure A.6 Class Digit for the object-oriented demo compiler.� �����������������������������������������������������������������������������������������������������������

286 Appendix A − A simple object-oriented compiler/interpreter

Page 287: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

class Parenthesized_Expression extends Expression {private Expression left;private Operator oper;private Expression right;

public boolean Parse_And() {if (Lex.Token_Class == ’(’) {

Lex.Get_Token();if ((left = Expression.Parse_Or()) == null) {

System.err.println("Missing left expression");return false;

}if ((oper = Operator.Parse_Or()) == null) {

System.err.println("Missing operator");return false;

}if ((right = Expression.Parse_Or()) == null) {

System.err.println("Missing right expression");return false;

}if (Lex.Token_Class != ’)’) {

System.err.println("Missing ) added");}else {Lex.Get_Token();}return true;

}return false;

}

public void Print() {System.out.print(’(’);left.Print(); oper.Print(); right.Print();System.out.print(’)’);

}

public int Interpret() {return oper.Interpret(left.Interpret(), right.Interpret());

}

public void Generate_Code() {left.Generate_Code();right.Generate_Code();oper.Generate_Code();

}}

Figure A.7 Class Parenthesized_Expression for the object-oriented demo compiler.� �����������������������������������������������������������������������������������������������������������

SECTION A.4 Evaluation 287

Page 288: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

abstract class Operator {public static Operator Parse_Or() {

// Try to parse a ’+’Actual_Operator co_plus = new Actual_Operator(’+’);if (co_plus.Parse_And()) return co_plus;

// Try to parse a ’*’Actual_Operator co_times = new Actual_Operator(’*’);if (co_times.Parse_And()) return co_times;

return null;}

abstract public void Print();abstract public int Interpret(int e_left, int e_right);abstract public void Generate_Code();

}

class Actual_Operator extends Operator {private char oper;

public Actual_Operator(char op) {oper = op;}

public boolean Parse_And() {if (Lex.Token_Class == oper) {Lex.Get_Token(); return true;}return false;

}

public void Print() {System.out.print(oper);}

public int Interpret(int e_left, int e_right) {switch (oper) {case ’+’: return e_left + e_right;case ’*’: return e_left * e_right;}return 0;

}

public void Generate_Code() {switch (oper) {case ’+’: System.out.print("ADD\n"); break;case ’*’: System.out.print("MULT\n"); break;}

}}

Figure A.8 Class Operator for the object-oriented demo compiler.� �����������������������������������������������������������������������������������������������������������

288 Appendix A − A simple object-oriented compiler/interpreter

Page 289: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

class A extends ... {private A1 a1; // fields for the componentsprivate A2 a2;...private An an;

public boolean Parse_And() {// Try to parse the alternative A1 A2 ... An:if ((a1 = A1.Parse_Or()) != null) {

if ((a2 = A2.Parse_Or()) == null)error("Missing A2");

...if ((an = An.Parse_Or()) == null)

error("Missing An");return true;

}return false;

}}

Figure A.9 The template for an AND non-terminal.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

abstract class A {public static A Parse_Or() {

// Try to parse an A1:A1 a1 = new A1();if (a1.Parse_And()) return a1;...// Try to parse an An:An an = new An();if (an.Parse_And()) return an;

return null;}

}

Figure A.10 The template for an OR non-terminal.� �����������������������������������������������������������������������������������������������������������

SECTION A.4 Evaluation 289

Page 290: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

More answers to exercises

290

Page 291: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

SET the flag There is a character _a_ buffered TO False;

PROCEDURE Accept filtered character Ch from previous module:IF There is a character _a_ buffered = True:

// See if this is a second ’a’:IF Ch = ’a’:

// We have ’aa’:SET There is a character _a_ buffered TO False;Output character ’b’ to next module;

ELSE Ch /= ’a’:SET There is a character _a_ buffered TO False;Output character ’a’ to next module;Output character Ch to next module;

ELSE IF Ch = ’a’:SET There is a character _a_ buffered TO True;

ELSE There is no character ’a’ buffered AND Ch /= ’a’:Output character Ch to next module;

PROCEDURE Flush:IF There is a character _a_ buffered:

SET There is a character _a_ buffered TO False;Output character ’a’ to next module;

Flush next module;

Figure Answers.1 The filter aa → b as a post-main module.� �����������������������������������������������������������������������������������������������������������

More answers to exercises 291

Page 292: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

void skip_layout_and_comment(void) {while (is_layout(input_char)) {next_char();}while (is_comment_starter(input_char)) {

skip_comment();while (is_layout(input_char)) {next_char();}

}}

void skip_comment(void) {next_char();while (!is_comment_stopper(input_char)) {

if (is_end_of_input(input_char)) return;else if (is_comment_starter(input_char)) {

skip_comment();}else next_char();

}next_char();

}

Figure Answers.2 Skipping layout and nested comment.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

T→α � (R 1&R 2& ...&Rn)β ⇒T→α � R 1(R 2&R 3& ...&Rn)βT→α � R 2(R 1&R 3& ...&Rn)β...T→α � Rn(R 1&R 2& ...&Rn −1)β

Figure Answers.3 ε move rule for the composition operator &.� �����������������������������������������������������������������������������������������������������������

292 More answers to exercises

Page 293: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

0 (1, 0) - (2, 0)1 (1, 1) - (2, 1)2 (3, 2) - -3 (3, 3) - -

�����������������������������������������������������������������������������������������������������������������������������������������

(1, 0) (1, 1) (2, 0) (2, 1) (3, 2) (3, 3) - -

Figure Answers.4 Fitting the strips with entries marked by state.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

%Start Comment

Layout ([ \t])

AnyQuoted (\\.)StringChar ([ˆ"\n\\]|{AnyQuoted})CharChar ([ˆ’\n\\]|{AnyQuoted})

StartComment ("/*")EndComment ("*/")SafeCommentChar ([ˆ*\n])UnsafeCommentChar ("*")

%%

\"{StringChar}*\" {printf("%s", yytext);} /* string */\’{CharChar}\’ {printf("%s", yytext);} /* character */

{Layout}*{StartComment} {BEGIN Comment;}<Comment>{SafeCommentChar}+ {} /* safe comment chunk */<Comment>{UnsafeCommentChar} {} /* unsafe char, read one by one */<Comment>"\n" {} /* to break up long comments */<Comment>{EndComment} {BEGIN INITIAL;}

Figure Answers.5 Lex filter for removing comments from C program text.� �����������������������������������������������������������������������������������������������������������

More answers to exercises 293

Page 294: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

GENERIC PROCEDURE F1(Type)(parameters to F1):SET the Type variable Var TO ...;// some code using Type and Var

GENERIC PROCEDURE F2(Type)(parameters to F2):FUNCTION F1_1(parameters to F1_1):

INSTANTIATE F1(Integer);FUNCTION F1_2(parameters to F1_2):

INSTANTIATE F1(Real);SET the Type variable Var TO ...;// some code using F1_1, F1_2, Type and Var

GENERIC PROCEDURE F3(Type)(parameters to F3):FUNCTION F2_1(parameters to F2_1):

INSTANTIATE F2(Integer);FUNCTION F2_2(parameters to F2_2):

INSTANTIATE F2(Real);SET the Type variable Var TO ...;// some code using F2_1, F2_2, Type and Var

Figure Answers.6 An example of exponential generics by macro expansion.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

%token IDENTIFIER%token EOF%%

input_suffix :expression_suffix EOF | EOF ;

expression :term | expression ’+’ term ;

expression_suffix :term_suffix | expression_suffix ’+’ term | ’+’ term ;

term :IDENTIFIER | ’(’ expression ’)’ ;

term_suffix :expression ’)’ | expression_suffix ’)’ | ’)’ ;

Figure Answers.7 An LALR(1) suffix grammar for the grammar of Figure 2.84.� �����������������������������������������������������������������������������������������������������������

294 More answers to exercises

Page 295: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

stack continuation FIRST setparenthesized_expression rest_expression EOF { ’(’ }’(’ expression ’)’ rest_expression EOF ’(’expression ’)’ rest_expression EOF { IDENTIFIER ’(’ }term rest_expression ’)’ rest_expression EOF { IDENTIFIER ’(’ }IDENTIFIER rest_expression ’)’ rest_expression EOF IDENTIFIERrest_expression ’)’ rest_expression EOF { ’+’ ε }’)’ rest_expression EOF ’)’rest_expression EOF { ’+’ ε }EOF EOF

Figure Answers.8 Stack continuations with their FIRST sets.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

✔ shift-reduceS1

0S

S3

Sx

2

S->.xSx{$}S->.x{$}

x S->x.Sx{x$}S->x.{x$}S->.xSx{x}S->.x{x}

S

S->xS.x{x$}

S->xSx.{x$}

x

Figure Answers.9 The SLR(1) automaton for S → x S x | x.� �����������������������������������������������������������������������������������������������

More answers to exercises 295

Page 296: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

✔ shift-reduce ✔ shift-reduce

3

S5

S6S

2Sx

4S1SS0

S->.xSx{$}S->.x{$}

x S->x.Sx{$}S->x.{$}S->.xSx{x}S->.x{x}

S

x S->x.Sx{x}S->x.{x}S->.xSx{x}S->.x{x}

S

S->xS.x{$}

S->xSx.{$}

x

S->xS.x{x}

S->xSx.{x}

x

Figure Answers.10 The LR(1) automaton for S → x S x | x.� �����������������������������������������������������������������������������������������������

296 More answers to exercises

Page 297: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

✔ shift-reduce ✔ shift-reduce

S5

S6

S2

4SS

S

01S

3

x

S->.xSx{$}S->.x{$}

x S->x.Sx{$}S->x.{$}S->.xSx{x}S->.x{x}

S

x S->x.Sx{x}S->x.{x}S->.xSx{x}S->.x{x}

S

S->xS.x{$}

S->xSx.{$}

x

S->xS.x{x}

S->xSx.{x}

x

Figure Answers.11 The LALR(1) automaton for S → x S x | x.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

if_statement → short_if_statement | long_if_statementshort_if_statement → ’if’ ’(’ expression ’)’ statementlong_if_statement →

’if’ ’(’ expression ’)’ statement_but_not_short_if’else’ statement

statement_but_not_short_if → long_if_statement | other_statementstatement → if_statement | other_statementother_statement → ...

Figure Answers.12 An unambiguous grammar for the if-then-else statement.� �����������������������������������������������������������������������������������������������������������

More answers to exercises 297

Page 298: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

S1

S->A.{$}

S

S

4a

0

A->B.{$}

S

2

4S

a

B

Ax

B->x.{$}S->x.b{$}

b

S->.A{$}S->.xb{$}A->.aAb{$}A->.B{$}

B->.x{$}A->.ERR{$}

A->ERR.{$}

ERR

Figure Answers.13 State S 0 of the error-recovering parser.� �����������������������������������������������������������������������������������������������

298 More answers to exercises

Page 299: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

FUNCTION Topological sort of (a set Set) RETURNING a list:SET List TO Empty list;SET Busy list TO Empty list;WHILE there is a Node in Set but not in List:

Append Node and its predecessors to List;RETURN List;

PROCEDURE Append Node and its predecessors to List:// Check if Node is already (being) dealt with; if so, there// is a cycle:IF Node is in Busy list:

Panic with "Cycle detected";RETURN;

Append Node to Busy list;// Append the predecessors of Node:FOR EACH Node_1 IN the Set of nodes that Node is dependent on:

IF Node_1 is not in List:Append Node_1 and its predecessors to List;

Append Node to List;

Figure Answers.14 Outline code for topological sort with cycle detection.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

i1 s1

i1 s1

i2 s2

A

A a

i1 s1

s2i2 B

A

i s

b

B

s

A

S

Figure Answers.15 Dependency graphs for S, A, and B.� �����������������������������������������������������������������������������������������������

More answers to exercises 299

Page 300: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

i1 s1

from S

from B

A

Figure Answers.16 IS-SI graph of A.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

s

s1i1 i2 s2

a

A s1i1 i2 s2

b

A

s1i1 i2 s2

S

A

Figure Answers.17 Dependency graphs for S and A.� �����������������������������������������������������������������������������������������������

300 More answers to exercises

Page 301: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

IS-SI graph set of :A

s1i1 i2 s2A s1i1 i2 s2A

merged IS-SI graph of :A

s1i1 i2 s2A

Figure Answers.18 IS-SI graph sets and IS-SI graph of A.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

s1i1 i2 s2

i1 s1s1 i1

S

T U

Figure Answers.19 Dependency graph of S.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

s1i1 i2 s2S

Figure Answers.20 IS-SI graph of S.� �����������������������������������������������������������������������������������������������

More answers to exercises 301

Page 302: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

s1i1 i2 s2S

Figure Answers.21 IS-SI graph of S.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

parent prepares S.i1 and S.i2:

PROCEDURE Visit to S (i1, i2, s1, s2):// S.i1 and S.i2 available →Visit to T (-, T.cont_i); // → T.cont_i availableSET U.i TO f2(S.i2); // → U.i availableVisit to U (U.i, U.s); // → U.s availableSET T.i TO f1(S.i1, U.s); // → T.i availableSET T.s TO Compute(T.cont_i, T.i) // → T.s availableSET S.s1 TO f3(T.s); // → S.s1 availableSET S.s2 TO f4(U.s); // → S.s2 available

Figure Answers.22 Visit to S().� �����������������������������������������������������������������������������������������������������������

302 More answers to exercises

Page 303: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

Number(SYN value) →Digit_Seq Base_TagATTRIBUTE RULES

SET Number .value TO Checked number value(Digit_Seq .repr,

Base_Tag .base);

Digit_Seq(SYN repr) →Digit_Seq[1] DigitATTRIBUTE RULES

SET Digit_Seq .repr TOConcat(Digit_Seq[1] .repr , Digit .repr);

|DigitATTRIBUTE RULES

SET Digit_Seq .repr TO Digit .repr;

Digit(SYN repr) →Digit_TokenATTRIBUTE RULES

SET Digit .repr TO Digit_Token .repr [0];

Base_Tag(SYN base) →’B’ATTRIBUTE RULES

SET Base_Tag .base TO 8;|

’D’ATTRIBUTE RULES

SET Base_Tag .base TO 10;

Figure Answers.23 An L-attributed grammar for Number.� �����������������������������������������������������������������������������������������������������������

More answers to exercises 303

Page 304: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

StatementsConditionX

While_statement

Figure Answers.24 Threaded AST of the while statement.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

Statements ConditionX

Repeat_statement

Figure Answers.25 Threaded AST of the repeat statement.� �����������������������������������������������������������������������������������������������

304 More answers to exercises

Page 305: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

#include "parser.h" /* for types AST_node and Expression */#include "thread.h" /* for self check */

/* PRIVATE */static AST_node *Thread_expression(Expression *expr, AST_node *succ) {

switch (expr->type) {case ’D’:

expr->successor = succ; return expr;break;

case ’P’:expr->successor = succ;return

Thread_expression(expr->left,Thread_expression(expr->right, expr)

);break;

}}

/* PUBLIC */AST_node *Thread_start;

void Thread_AST(AST_node *icode) {Thread_start = Thread_expression(icode, 0);

}

Figure Answers.26 Alternative threading code for the demo compiler from Section 1.2.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

CASE Operator type:SET Left value TO Pop working stack ();SET Right value TO Pop working stack ();SELECT Active node .operator:

CASE ’+’: Push working stack (Left value + Right value);CASE ’*’: ...CASE ...

SET Active node TO Active node .successor;

Figure Answers.27 Iterative interpreter code for operators.� �����������������������������������������������������������������������������������������������������������

More answers to exercises 305

Page 306: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

FUNCTION Weight of (Node) RETURNING an integer:SELECT Node .type:

CASE Constant type: RETURN 1;CASE Variable type: RETURN 1;CASE ...CASE Add type:

SET Required left TO Weight of (Node .left);SET Required right TO Weight of (Node .right);IF Required left > Required right: RETURN Required left;IF Required left < Required right: RETURN Required right;// Required left = Required rightRETURN Required left + 1;

CASE Sub type:SET Required left TO Weight of (Node .left);SET Required right TO Weight of (Node .right);IF Required left > Required right: RETURN Required left;RETURN Required right + 1;

CASE ...

Figure Answers.28 Adapted weight function for minimizing the stack height.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

FUNCTION Weight of (Node, Left or right) RETURNING an integer:SELECT Node .type:

CASE Constant type: RETURN 1;CASE Variable type:

IF Left or right = Left: RETURN 1;ELSE Left or right = Right: RETURN 0;

CASE ...CASE Add type:

SET Required left TO Weight of (Node .left, Left);SET Required right TO Weight of (Node .right, Right);IF Required left > Required right:

RETURN Required left;IF Required left < Required right:

RETURN Required right;// Required left = Required rightRETURN Required left + 1;

CASE ...

Figure Answers.29 Revised weight function for register-memory operations.� �����������������������������������������������������������������������������������������������������������

306 More answers to exercises

Page 307: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

Equation Valuea = 1 1.0b = 0.7 a 0.7c = 0.3 a 0.3d = b 0.7e = 0.1 (d+f) 0.7f = g 6.3g = 0.9 (d+f) 6.3h = c 0.3i = 0.4 h 0.12j = 0.4 h 0.12k = 0.2 h 0.06l = i 0.12m = j 0.12n = k 0.06o = e 0.7p = l+m+n 0.30q = o+p 1.0

Figure Answers.30 Traffic equations and their solution for Figure 4.97.� �����������������������������������������������������������������������������������������������������������

More answers to exercises 307

Page 308: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

whilec b

a

d

A

g

whilei h

j

B

Figure Answers.31 Flow graph for static profiling of a nested while loop.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

Equation Valuea = 1 1.0b = i 9.0c = 0.1 (a+b) 1.0d = 0.9 (a+b) 9.0e = d 9.0f = e 9.0g = f 9.0h = j 81.0i = 0.1 (g+h) 9.0j = 0.9 (g+h) 81.0

Figure Answers.32 Traffic equations and their solution for Figure Answers.31.� �����������������������������������������������������������������������������������������������������������

308 More answers to exercises

Page 309: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

+

x

+ *

*

a a

*

*

2 a

b

b b

+

*

*

a a

*

*

2 a

b

b b

-

y

Figure Answers.33 The dependency graph before common subexpression elimination.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

+

y

+

x

+ *

* *

*

2

a

b-

Figure Answers.34 The dependency graph after common subexpression elimination.� �����������������������������������������������������������������������������������������������

More answers to exercises 309

Page 310: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

+

p 1

=:

p

*

Figure Answers.35 The dependency graph of the expression *p++.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

position triple1 a * a2 a * 23 @2 * b4 @1 + @35 b * b6 @4 + @57 @6 =: x8 @1 - @39 @8 + @510 @9 =: y

Figure Answers.36 The data dependency graph of Figure Answers.34 in triple representation.� �����������������������������������������������������������������������������������������������������������

310 More answers to exercises

Page 311: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

+

y

*

* *

*

2

a

b-

R2 R3

R4

Figure Answers.37 The dependency graph of Figure Answers.34 with first ladder sequenceremoved.

� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

*

* *

*

2

a

b

R2 R3

R4

Figure Answers.38 The dependency graph of Figure Answers.37 with second ladder sequenceremoved.

� �����������������������������������������������������������������������������������������������

More answers to exercises 311

Page 312: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

*

*

a

b

R2

R4

Figure Answers.39 The dependency graph of Figure Answers.38 with third ladder sequenceremoved.

� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

*

b

R4

Figure Answers.40 The dependency graph of Figure Answers.39 with fourth ladder sequenceremoved.

� �����������������������������������������������������������������������������������������������

312 More answers to exercises

Page 313: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

a8

4

b

+

->cst @0R0#1->reg @1R1

->mem @0R0#2->reg @3R1

#5,9->mem @20R1

#4->reg @13R2#7->reg @14R2

->mem @0R0#2->reg @3R1

#1->reg @1R1->cst @0R0

#3->reg @18R2#3->reg @26R1

#8->reg @9R2

#5->reg @17R1

#8,9->mem @12R2

#5->reg @7R1#5,9->mem @10R1#6->reg @8R2

#1,9->mem @4R1

#1,9->mem @4R1

✔✔

*

*

Figure Answers.41 Bottom-up pattern matching with costs and register usage.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

Load_Const 8,R ; 1 unitMult_Mem a,R ; 6 unitsStore_Reg R,tmp ; 3 unitsLoad_Const 4,R ; 1 unitMult_Mem tmp,R ; 6 unitsStore_Reg R,tmp ; 3 unitsLoad_Mem b,R ; 3 unitsAdd_Mem tmp,R ; 3 units

Total = 26 units

Figure Answers.42 Code generated by bottom-up pattern matching for 1 register.� �����������������������������������������������������������������������������������������������������������

More answers to exercises 313

Page 314: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

tmp_2ab tmp_bb x y

b tmp_aa

a

Figure Answers.43 The register interference graph for Exercise {#IntGr2}.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

SET the polymorphic chunk pointer Scan pointer TOBeginning of available memory;

FUNCTION Malloc (Block size) RETURNING a polymorphic block pointer:SET Pointer TO Pointer to free block of size (Block size);IF Pointer /= Null pointer: RETURN Pointer;

Perform the marking part of the garbage collector;

SET Scan pointer TO Beginning of available memory;SET Pointer TO Pointer to free block of size (Block size);IF Pointer /= Null pointer: RETURN Pointer;

RETURN Solution to out of memory condition (Block size);

FUNCTION Pointer to free block of size (Block size)RETURNING a polymorphic block pointer:// Note that this is not a pure functionSET Chunk pointer TO First_chunk pointer;SET Requested chunk size TO Administration size + Block size;

WHILE Chunk pointer /= One past available memory:IF Chunk pointer >= Scan pointer:

Scan chunk at (Chunk pointer);IF Chunk pointer .free:

Coalesce with all following free chunks (Chunk pointer);IF Chunk pointer .size - Requested chunk size >= 0:

// large enough chunk found:Split chunk (Chunk pointer, Requested chunk size);SET Chunk pointer .free TO False;RETURN Chunk pointer + Administration size;

// try next chunk:SET Chunk pointer TO Chunk pointer + Chunk pointer .size;

RETURN Null pointer;

Figure Answers.44 A Malloc() with incremental scanning.� �����������������������������������������������������������������������������������������������������������

314 More answers to exercises

Page 315: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

PROCEDURE Scan chunk at (Chunk pointer):IF Chunk pointer .marked = True:

SET Chunk pointer .marked TO False;ELSE Chunk pointer .marked = False:

SET Chunk pointer .free TO True;SET Scan pointer TO Chunk pointer + Chunk pointer .size;

PROCEDURE Coalesce with all following free chunks (Chunk pointer):SET Next_chunk pointer TO Chunk pointer + Chunk pointer .size;IF Next_chunk pointer >= Scan pointer:

Scan chunk at (Next_chunk pointer);WHILE Next_chunk pointer /= One past available memory

AND Next_chunk pointer .free:// Coalesce them:SET Chunk pointer .size TO

Chunk pointer .size + Next_chunk pointer .size;SET Next_chunk pointer TO Chunk pointer + Chunk pointer .size;IF Next_chunk pointer >= Scan pointer:

Scan chunk at (Next_chunk pointer);

Figure Answers.45 Auxiliary routines for the Malloc() with incremental scanning.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

zeroth_offset (A) = −(LB 1×LEN_PRODUCT 1

+LB 2×LEN_PRODUCT 2

...

+LBn×LEN_PRODUCTn)

Figure Answers.46 Formula for zeroth_offset(A).� �����������������������������������������������������������������������������������������������

More answers to exercises 315

Page 316: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������

base (A)+zeroth_offset (A)

+i 1×LEN_PRODUCT 1+...+in×LEN_PRODUCTn

Figure Answers.47 The address of A[i 1 , ..., in].� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������

method table for Squaremethod table for Rectangle

IsShape_Shape_Shape

IsRectangle_Shape_Rectangle

IsSquare_Shape_Shape

SurfaceArea_Shape_Rectangle

IsShape_Shape_Shape

IsRectangle_Shape_Rectangle

SurfaceArea_Shape_Rectangle

IsSquare_Shape_Square

Figure Answers.48 Method tables for Rectangle and Square.� �����������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

FUNCTION Instance of (Obj, Class) RETURNING a boolean;SET Object Class TO Obj. Class;WHILE Object Class /= No class:

IF Object Class = Class:RETURN true;

ELSE Object Class /= Class:SET Object Class TO Object Class .Parent;

RETURN false;

Figure Answers.49 Implementation of the instanceof operator.� �����������������������������������������������������������������������������������������������������������

316 More answers to exercises

Page 317: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

void do_elements(int n, int element()) {int elem = read_integer();

int new_element(int i) {return (i == n ? elem : element(i));

}

if (elem == 0) {printf("median = %d0, element((n-1)/2));

}else {

do_elements(n + 1, new_element);}

}

void print_median(void) {int error(int i) {

printf("There is no element number %d0, i);abort();

}do_elements(0, error);

}

Figure Answers.50 Code for implementing an array without using an array.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

tmp_hash_entry := get_hash_entry(case expression);IF tmp_hash_entry = NO_ENTRY THEN GOTO label_else;GOTO tmp_hash_entry.label;

label_1:code for statement sequence 1

GOTO label_next;...

label_n:code for statement sequencen

GOTO label_next;label_else:

code for else-statement sequencelabel_next:

Figure Answers.51 Intermediate code for a hash-table implementation of case statements.� �����������������������������������������������������������������������������������������������������������

More answers to exercises 317

Page 318: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

expr1;while (expr2) {

body;forloop_continue_label:

expr3;/* whileloop_continue_label: */}

Figure Answers.52 A while loop that is exactly equivalent to the for-loop of Figure 6.41.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

i := lower bound;tmp_ub := upper bound - unrolling factor + 1;IF i > tmp_ub THEN GOTO end_label;tmp_loop_count := (tmp_ub - i) DIV unrolling factor + 1;

loop_label:code for statement sequencei := i + 1;...code for statement sequencei := i + 1; // these two lines unrolling factor timestmp_loop_count := tmp_loop_count - 1;IF tmp_loop_count = 0 THEN GOTO end_label;GOTO loop_label;

end_label:

Figure Answers.53 Loop-unrolling code.� �����������������������������������������������������������������������������������������������������������

318 More answers to exercises

Page 319: Introduction - cs.vu.nl · PDF fileProgram Compiler txt txt X Compiler exe exe Y = = Executable compiler code Compiler source text Input in code for target Executable program language

� �����������������������������������������������������������������������������������������������������������

unique a1 = if (_type_constr a1 == Cons &&_type_constr (_type_field 2 a1) == Cons) then

leta = _type_field 1 a1b = _type_field 1 (_type_field 2 a1)cs = _type_field 2 (_type_field 2 a1)

inif (a == b) then a : unique cselse a : unique (b:cs)

elsea1

Figure Answers.54 A functional-core equivalent of the function unique.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

qsort [] = []qsort (x:xs) = qsort (mappend qleft xs) ++ [x]

++ qsort (mappend qright xs)where

qleft y = if (y < x) then [y] else []qright y = if (y >= x) then [y] else []

Figure Answers.55 A functional-core equivalent of the function qsort.� �����������������������������������������������������������������������������������������������������������

� �����������������������������������������������������������������������������������������������������������

qsort [] = []qsort (x:xs) = qsort (mappend (qleft x) xs) ++ [x]

++ qsort (mappend (qright x) xs)

qleft x y = if (y < x) then [y] else []

qright x y = if (y >= x) then [y] else []

Figure Answers.56 A functional-core lambda-lifted equivalent of the function qsort.� �����������������������������������������������������������������������������������������������������������

More answers to exercises 319