Top Banner
Lesson 3 Two topics 1. Semantic Analysis 2. Translation to intermediate code Presented as separated topics but can be implemented together.
21

Lesson 3 Two topics 1. Semantic Analysis 2. Translation to intermediate code Presented as separated topics but can be implemented together.

Dec 28, 2015

Download

Documents

Bertha Allison
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Lesson 3 Two topics 1. Semantic Analysis 2. Translation to intermediate code Presented as separated topics but can be implemented together.

Lesson 3

• Two topics 1. Semantic Analysis

2. Translation to intermediate code

• Presented as separated topics but can be implemented together.

Page 2: Lesson 3 Two topics 1. Semantic Analysis 2. Translation to intermediate code Presented as separated topics but can be implemented together.

Symbols and symbol tables

• Given code implements structure Symbol.Symbol.symbol : string -> Symbol.symbol

Symbol.name : Symbol.symbol -> string

empty :'a table

enter :'a table * symbol * 'a -> 'a table

look :'a table * symbol -> 'a option

Page 3: Lesson 3 Two topics 1. Semantic Analysis 2. Translation to intermediate code Presented as separated topics but can be implemented together.

Symbols and symbol tables (2)

• When to convert a string to a symbol?

• What to put in the symbol table?

Depends on the use of the symbol table. For type checking one could associate:

• Type of the symbol.

• Nesting level

with each symbol.

Page 4: Lesson 3 Two topics 1. Semantic Analysis 2. Translation to intermediate code Presented as separated topics but can be implemented together.

Semantic Analysis

• The goal of the semantic analysis is to determine whether a program is semantically correct.

• That is, find errors that has to do with the meaning of the program (as opposed to the syntax of the program).

• For example, check that the program is correctly typed, e.g. don’t let the programmer write:

True + 42;

Page 5: Lesson 3 Two topics 1. Semantic Analysis 2. Translation to intermediate code Presented as separated topics but can be implemented together.

Semantic Analysis in Bar (1)

• What to detect.– Undefined symbols– Multiply defined symbols– Type errors– etc... (see definition and example files.)

• How to detect it.– By recursion over the Absyn structure.

Page 6: Lesson 3 Two topics 1. Semantic Analysis 2. Translation to intermediate code Presented as separated topics but can be implemented together.

Semantic Analysis in Bar (2)

Example: MINI-Float Goal: To detect undefined variables.Absyn: datatype expr =

FloatE of real | IdE of Symbol.symbol * pos | AddE of expr * expr * pos datatype stmnt = AssS of Symbol.symbol * expr * pos | PrintS of expr * pos datatype prog = BarProg of stmnt list

Page 7: Lesson 3 Two topics 1. Semantic Analysis 2. Translation to intermediate code Presented as separated topics but can be implemented together.

structure Env = struct

structure S = Symbol

type environment = {ok:bool, table: bool S.table}

val empty = {ok=true, table=S.empty}

fun enter({ok,table}, id) = {ok=ok, table = S.enter(table,id,true)}

fun set_ok({table,ok}:environment,newok) = {ok=ok andalso newok, table=table}

fun isok({ok,...}:environment) = ok

fun isDefined(id, {ok,table}) = case S.look(table, id) of SOME _ => true | NONE => false

end

Environment for semantic analysis of MINI-Float

Page 8: Lesson 3 Two topics 1. Semantic Analysis 2. Translation to intermediate code Presented as separated topics but can be implemented together.

fun msg_undef (id, pos) = (ErrorMsg.error pos ("Variable " ^ S.name(id) ^ " not defined."); false)

fun expr(A.FloatE(f), env) = true | expr(A.IdE(id, pos), env) = Env.isDefined(id, env) orelse (msg_undef (id,pos)) | expr(A.AddE(e1, e2, pos), env) = expr(e1, env) andalso expr(e2, env)

fun stmnt(A.AssS(id, e, pos), env) = Env.set_ok(Env.enter(env, id), expr(e, env))

| stmnt(A.PrintS(e, pos), env) =Env.set_ok(env, expr(e, env))

fun program(A.BarProg(statements)) =Env.isok(foldl stmnt Env.empty statements)

Semantic analysis of MINI-Float

Page 9: Lesson 3 Two topics 1. Semantic Analysis 2. Translation to intermediate code Presented as separated topics but can be implemented together.

Notes on semantic analysis of Bar

• The analysis of Bar will be much more complex.

• The type of expressions needs to be returned.

• Nested scopes needs to be handled.

• Return types of functions need to be handled.

• One-pass is OK, two-pass is optional.

Page 10: Lesson 3 Two topics 1. Semantic Analysis 2. Translation to intermediate code Presented as separated topics but can be implemented together.

Translation to intermediate code

• Turn the abstract synatax tree into a tree representing the instructions to be executed by the program.

• Also solved by recursion over the Absyn structure.

Page 11: Lesson 3 Two topics 1. Semantic Analysis 2. Translation to intermediate code Presented as separated topics but can be implemented together.

Given code:

• IR-Tree: The tree structure you are to translate to.

• Frames:A signature for the frame structure is given.(To implement the frame structure you will have to read up about calling conventions in the SPIM manual.)

• Backend:Names of runtime functions (such as PRINTBOOL) are given.

Page 12: Lesson 3 Two topics 1. Semantic Analysis 2. Translation to intermediate code Presented as separated topics but can be implemented together.

datatype etype = INT | FLOAT (* Expresion types *)datatype cond = LT | LE | EQ | NE | GE | GTdatatype unop = ILOAD (* load integer ( *expr ) *) | FLOAD (* load float *) | IMOVE of temp (* reg := expr *) | FMOVE of ftemp (* freg := expr *) | ITOF of ftemp (* freg := integer-expr *)datatype binop = IADD | ISUB | IMUL | IDIV (* int * int -> int *) | FADD | FSUB | FMUL | FDIV (* float * float -> float *) | AND | OR (* int * int -> int *) | ICMP of cond (* int * int -> int *) | FCMP of cond (* float * float -> int *) | ISTORE (* MEM[exp1] := exp2 *) | FSTORE (* MEM[exp1] := exp2 *) | RNGCHK (* if (0 <= exp1 < exp2) then exp1 else error *)datatype exp = TEMP of temp (* Temporary value in reg *) | FTEMP of ftemp (* Temporary value in reg *) | ICON of int (* Integer constant *)

| UNARY of unop * exp | BINARY of binop * exp * exp | LABREF of label | CALL of etype * label * ((etype * exp) list)

IR Tree (1)

Page 13: Lesson 3 Two topics 1. Semantic Analysis 2. Translation to intermediate code Presented as separated topics but can be implemented together.

datatype insn = LABDEF of label (* Label *) | JUMP of label (* GOTO *) | CJUMP of exp * label (* Conditional branch e=1 *) | IGNORE of etype * exp (* Expression used for

side-effects only *)

datatype dec = PROC of (* Function and procs *) {label: label, localsSize: int, insns: insn list} | DATA of (* Uninitialised data *) {label: label, size: int} | FCONST of (* Initialised fp-data *) {label: label, float: real}

datatype program = PROGRAM of dec list

IR Tree (2)

Page 14: Lesson 3 Two topics 1. Semantic Analysis 2. Translation to intermediate code Presented as separated topics but can be implemented together.

structure Env = struct type bindings = I.label type environment = {env: bindings S.table, globals: I.dec list}

val empty = {env = S.empty, globals=[]}:environment

fun enter_gvar({env, globals}, name, loc) = {env = S.enter(env, name, loc), globals= (I.DATA{label = loc, size = 2})::globals}:environment fun enter_float({env, globals}, f, lab) = {env = env, globals = (I.FCONST{label = lab, float = f}) ::globals}:environment

fun var({env,...}:environment, id) = case S.look(env, id) of

SOME loc => loc | _ => ErrorMsg.impossible("Trying to ref a nonvar.")

fun globals({globals,...}:environment) = globalsend

Environment for translation to IR of MINI-Float

Page 15: Lesson 3 Two topics 1. Semantic Analysis 2. Translation to intermediate code Presented as separated topics but can be implemented together.

fun expr2icode(A.FloatE(f), env) = let

val name = R.new_label() in

(Env.enter_float(env,f,name), I.UNARY(I.FLOAD, I.LABREF name)) end

| expr2icode(A.IdE(id,pos),env) = (env,I.UNARY(I.FLOAD,

I.LABREF(Env.var(env,id)))) | expr2icode(A.AddE(e1,e2,pos),env) =

let val (env1,icode1) = expr2icode(e1,env) val (env2,icode2) = expr2icode(e2,env1)

in (env2, I.BINARY(I.FADD, icode1, icode2))

end

Translation of expressions in MINI-Float

Page 16: Lesson 3 Two topics 1. Semantic Analysis 2. Translation to intermediate code Presented as separated topics but can be implemented together.

fun stmnt2icode(A.AssS(id, e, pos), env) = let val (env1, expricode) = expr2icode(e, env) val lab = R.varLabel id val newenv = Env.enter_gvar(env1, id, lab) in

(newenv, I.IGNORE(I.FLOAT, I.BINARY(I.FSTORE,

I.LABREF lab, expricode)))

end | stmnt2icode(A.PrintS(e, pos),env) = let val (env1,expricode) = expr2icode(e, env) in

(env1, I.IGNORE(I.INT, I.CALL(I.INT, R.labPrintFloat,[(I.FLOAT,expricode)])))

endand stmnts2icode(s::statements, env) = let val (newenv,icode) = stmnt2icode(s,env) val (finalenv,moreicode) = stmnts2icode(statements,newenv) in (finalenv, icode::moreicode) end| stmnts2icode([],env) = (env,[])

Translation of statements in MINI-Float

Page 17: Lesson 3 Two topics 1. Semantic Analysis 2. Translation to intermediate code Presented as separated topics but can be implemented together.

fun syn2icode(A.BarProg(stmnts)) = let val (env, insns) = stmnts2icode(stmnts, Env.empty) in

I.PROGRAM(I.PROC{label=R.labMain, localsSize=0, insns=insns}::Env.globals(env))

end

Translation of programs in MINI-Float

Page 18: Lesson 3 Two topics 1. Semantic Analysis 2. Translation to intermediate code Presented as separated topics but can be implemented together.

Translation to intermediate code

• The Bar language will be much more complicated.

• Function calls has to be handled.

• Locations of parameters, local-, static- and globalvaraibles has to be handled.

• Conversions between int and floats has to be handled.

Page 19: Lesson 3 Two topics 1. Semantic Analysis 2. Translation to intermediate code Presented as separated topics but can be implemented together.

The frame siganture (1)val wordSize : int

(* Locations for formals, locals, and the return value.*)type temp = inttype ftemp = intdatatype vtype = INT | FLOAT

datatype location = TEMP of temp | FTEMP of ftemp | OFF of temp * int

val RV : locationval FRV : location

Page 20: Lesson 3 Two topics 1. Semantic Analysis 2. Translation to intermediate code Presented as separated topics but can be implemented together.

The frame siganture (2)

(* Locations of formal parameters. *)type formalsval initFormals : unit -> formalsval nextFormal : formals * vtype -> formals * locationval formalsStackNeed : formals -> int

(* Locations of local variables. *)type localsval initLocals : unit -> localsval nextScalar : locals * vtype -> locals * locationval nextArray : locals * vtype * int -> locals * location

Page 21: Lesson 3 Two topics 1. Semantic Analysis 2. Translation to intermediate code Presented as separated topics but can be implemented together.

Runtime supportfun procLabel id = Symbol.symbol("P_" ^ (Symbol.name id))fun varLabel id = Symbol.symbol("V_" ^ (Symbol.name id))

val labMain = Symbol.symbol "main"val labPrintInt = Symbol.symbol "PRINTINT"val labPrintBool = Symbol.symbol "PRINTBOOL"val labPrintFloat = Symbol.symbol "PRINTFLOAT"val labTrunc = Symbol.symbol "TRUNC"val labRead = Symbol.symbol "READINT"val labReadBool = Symbol.symbol "READBOOL"val labReadFloat = Symbol.symbol "READFLOAT"val labRangeError = Symbol.symbol "RANGEERROR"local val labnr = ref 0 in fun new_label () = (labnr := !labnr + 1; Symbol.symbol("Label_" ^ (Int.toString (!labnr))))end