Lecture Notes on Context-Sensitive Analysis - Introduction to Compilers | CMSC 430, Study notes of Computer Science

Material Type: Notes; Class: INTRO TO COMPILERS; Subject: Computer Science; University: University of Maryland; Term: Unknown 1989;

Typology: Study notes

Pre 2010

Uploaded on 02/13/2009

koofers-user-mwl
koofers-user-mwl ๐Ÿ‡บ๐Ÿ‡ธ

9 documents

1 / 17

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
Context-sensitive analysis
What context-sensitive questions might the compiler ask?
1. Is xa scalar, an array, or a function?
2. Is xdeclared before it is used?
3. Are any names declared but not used?
4. Which declaration of xdoes this reference?
5. Is an expression type-consistent?
6. Does the dimension of a reference match the declaration?
7. Where can xbe stored? (heap, stack, . . . )
8. Does *p reference the result of a malloc()?
9. Is xdefined before it is used?
10. Is an array reference in bounds?
11. Does function foo produce a constant value?
These cannot be answered with a context-free grammar
CMSC 430 Lecture 6, Page 1
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff

Partial preview of the text

Download Lecture Notes on Context-Sensitive Analysis - Introduction to Compilers | CMSC 430 and more Study notes Computer Science in PDF only on Docsity!

Context-sensitive analysis

What context-sensitive questions might the compiler ask?

  1. Is x a scalar, an array, or a function?
  2. Is x declared before it is used?
  3. Are any names declared but not used?
  4. Which declaration of x does this reference?
  5. Is an expression type-consistent?
  6. Does the dimension of a reference match the declaration?
  7. Where can x be stored? (heap, stack,... )
  8. Does *p reference the result of a malloc()?
  9. Is x defined before it is used?
  10. Is an array reference in bounds?
  11. Does function foo produce a constant value?

These cannot be answered with a context-free grammar

Context-sensitive analysis

Why is context-sensitive analysis hard?

  • need non-local information
  • answers depend on values, not on syntax
  • answers may involve computation

How can we answer these questions?

  1. use context-sensitive grammars
    • general problem is P-space complete
  2. use attribute grammars
    • augment context-free grammar with rules
    • calculate attributes for grammar symbols
  3. use ad hoc techniques
    • augment grammar with arbitrary code
    • execute code at corresponding reduction
    • store information in attributes, symbol tables

Example attribute grammar

A grammar to evaluate signed binary numbers due to Scott K. Warren, Rice Ph.D.

Production Evaluation Rules 1 NUM ::= SIGN LIST LIST.pos โ† 0 NUM.val โ† if SIGN.neg then -LIST.val else LIST.val 2 SIGN ::= + SIGN.neg โ† false 3 SIGN ::= - SIGN.neg โ† true 4 LIST ::= BIT BIT.pos โ† LIST.pos LIST.val โ† BIT.val 5 LIST 0 ::= LIST 1 BIT LIST 1 .pos โ† LIST 0 .pos + 1 BIT.pos โ† LIST 0 .pos LIST 0 .val โ† LIST 1 .val + BIT.val 6 BIT ::= 0 BIT.val โ† 0 7 BIT ::= 1 BIT.val โ† 2 BIT.pos

Example attribute grammar

NUM val: -

SIGN neg: T

pos: 0 LIST val: 5

pos: 1 LIST val: 4

pos: 2 LIST val: 4

pos: 2 BIT val: 4

pos: 1 BIT val: 0

pos: 0 BIT val: 1

  • val and neg are synthesized attributes
  • pos is an inherited attribute

Abstract syntax tree

An abstract syntax tree (AST) is the procedureโ€™s parse tree with the nodes for most non-terminal symbols removed.

<id,x> *

<num, 2 > <id,y>

This represents โ€œx - 2 * yโ€.

For ease of manipulation, can use a linearized (operator) form of the tree.

x 2 y * - in postfix form.

A popular intermediate representation.

Symbol tables

A symbol table associates values or attributes (e.g., types and values) with names.

What should be in a symbol table?

  • variable and procedure names
  • literal constants and strings

What information might compiler need?

  • textual name
  • data type
  • declaring procedure
  • lexical level of declaration
  • if array, number and size of dimensions
  • if procedure, number and type of parameters

Type systems

Types

  • values that share a set of common properties
  • defined by language and/or programmer

Type system

  1. set of types in a programming language, and
  2. rules that use types to specify program behavior

Example type rules

  • If operands of addition are of type integer, then result is of type integer
  • The result of the unary & operator is a pointer to the object referred to by the operand

Advantages of typed languages

  • ensure run-time safety
  • expressiveness (overloading, polymorphism)
  • provide information for code generation

Type checking

Type checker

  • enforces rules of type system
  • may be strong/weak, static/dynamic

Static type checking

  • performed at compile time
  • early detection, no run-time overhead
  • not always possible (e.g., A[i])

Dynamic type checking

  • performed at run time
  • more flexible, rapid prototyping
  • overhead to check run-time type tags

A simple type checker

Using a synthesized attribute grammar, we will describe a type checker for arrays, pointers, statements, and functions.

Grammar for source language:

P ::= D ; E D ::= D ; E | id: T T ::= char | integer | array [num] of T | โ†‘ T E ::= literal | num | id | E mod E | E[E] | E โ†‘

  • Basic types char, integer, typeError
  • assume all arrays start at 1, e.g., array [256] of char results in the type expression array(1.. .256,char)
  • โ†‘ builds a pointer type, so โ†‘ integer results in the type expression pointer(integer)

Type checking example

Partial attribute grammar for the type system

D ::= id: T { addtype(id.entry, T.type) } T ::= char { T.type โ† char } T ::= integer { T.type โ† integer } T ::= โ†‘ T 1 { T.type โ† pointer(T 1 .type) } T ::= array [num] of T 1 { T.type โ† array( 1.. .num.val, T 1 .type) }

Type checking statements

Statements do not typically have values, therefore we assign them the type void. If an error is detected within the statement, it gets type typeError.

S ::= id โ† E { S.type โ† if id.type = E.type then void else typeError } S ::= if E then S 1 { S.type โ† if E.type = boolean then S 1 .type else typeError } S ::= while E do S 1 { S.type โ† if E.type = boolean then S 1 .type else typeError } S ::= S 1 ; S 2 { S.type โ† if S 1 .type = void then void else typeError }

Type checking functions

We add two new productions to the grammar to represent function declarations and applications

T ::= T โ†’ T declaration E ::= E ( E ) application

To capture the argument and return type, we use

T ::= T 1 โ†’ T 2 { T.type โ† (T 1 .type โ†’ T 2 .type) }

E ::= E 1 ( E 2 ) { E.type โ† if E 1 .type = s โ†’ t and E 2 .type = s then t else typeError }