21
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

Embed Size (px)

Citation preview

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