Context Sensitive Analysis - Lecture Notes | CMSC 430, Study notes of Computer Science

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

Typology: Study notes

Pre 2010

Uploaded on 07/30/2009

koofers-user-68k
koofers-user-68k ๐Ÿ‡บ๐Ÿ‡ธ

10 documents

1 / 9

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
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
CMSC 430 Lecture 6, Page 2
pf3
pf4
pf5
pf8
pf9

Partial preview of the text

Download Context Sensitive Analysis - Lecture Notes | 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

CMSC 430 Lecture 6, Page 1

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

Attribute grammars

Attribute grammar

  • generalization of context-free grammar
  • each grammar symbol has an associated set of attributes
  • augment grammar with rules that define values
  • high-level specification, independent of evaluation scheme

Dependences between attributes

  • values are computed from constants & other attributes
  • synthesized attribute โ€“ value computed from children
  • inherited attribute โ€“ value computed from siblings & parent

CMSC 430 Lecture 6, Page 3

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

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.

CMSC 430 Lecture 6, Page 7

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

Symbol tables

Implementation

  • usually implemented as hash tables

How to handle nested lexical scoping?

  • when we ask about a name, we want the closest lexical declaration

One solution

  • use one symbol table per scope
  • tables chained to enclosing scopes
  • insert names in table for current scope
  • name lookup starts in current table if needed, checks enclosing scopes in order

CMSC 430 Lecture 6, Page 9

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

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)

CMSC 430 Lecture 6, Page 13

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 expressions

Each expression is assigned a type using rules associated with the grammar.

E ::= literal { E.type โ† char } E ::= num { E.type โ† integer } E ::= id { E.type โ† lookup(id.entry) } E ::= E 1 mod E 2 { E.type โ† if E 1 .type = integer and E 2 .type = integer then integer else typeError } E ::= E 1 [E 2 ] { E.type โ† if E 2 .type = integer and E 1 .type = array(s,t) then t else typeError } E ::= E 1 โ†‘ { E.type โ† if E 1 .type = pointer then t else typeError }

CMSC 430 Lecture 6, Page 15

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 }