210 likes | 389 Views
Parameter Passing. COP 3402 Software Systems Spring 2014. Parameter Passing. Passing parameter to procedures (instead of using variables) simplifies some types of programs, i.e., recursive procedures. int a, b; procedure sum; int c; begin c := a + b; write c; end; begin a = 2;
E N D
Parameter Passing COP 3402 Software Systems Spring 2014
Parameter Passing • Passing parameter to procedures (instead of using variables) simplifies some types of programs, i.e., recursive procedures. int a, b; procedure sum; int c; begin c := a + b; write c; end; begin a = 2; b = 3; call sum; end. procedure sum(a,b); int c; begin c := a + b; write c; end; begin call sum(2,3); end.
Parameter Passing • To implement parameter passing we must modify: • Grammar • Activation Record • Parsing • Code generation
Grammar Changes program ::= block "." . block ::= const-declaration var-declaration procedure-declaration statement. const-declaration ::= ["const"ident "=" number {"," ident "=" number} ";"]. var-declaration ::= [ "int "ident {"," ident} “;"]. procedure-declaration ::= { "procedure" ident ";" block ";" } statement ::= [ ident ":=" expression | "call" ident | "begin" statement { ";" statement } "end" | "if" condition "then" statement ["else" statement] | "while" condition "do" statement | "read" ident | "write" expression | e ] . ...
Grammar Changes program ::= block "." . block ::= const-declaration var-declaration procedure-declaration statement. const-declaration ::= ["const"ident "=" number {"," ident "=" number} ";"]. var-declaration ::= [ "int "ident {"," ident} “;"]. procedure-declaration ::= { "procedure" identparam-block ";" block ";" }. param-block ::= "(" [ ident { "," ident} ] ")". param-list ::= "(" [ expression { "," expression} ] ")". statement ::= [ ident ":=" expression | "call" identparam-list | "begin" statement { ";" statement } "end" | "if" condition "then" statement ["else" statement] | "while" condition "do" statement | "read" ident | "write" expression | e ]. ...
Activation Record Changes • The AR must be expanded to include the Parameter Slots. Return Value Return Value Static Link Static Link Dynamic Link Dynamic Link Return Address Return Address Int Slots Param Slots … … Int Slots …
PROC-DECL Procedure procedure-declaration ::= { "procedure" ident ";" block ";" }. procedure PROC-DECL (level); begin while TOKEN = "procedure" do begin GET_TOKEN(); if TOKEN <> IDENT then ERROR (missing procedure declaration); ENTER(procedure, ident); GET_TOKEN(); if TOKEN <> ";" then ERROR (procedure declaration must end with ;); GET_TOKEN(); BLOCK(level+1); if TOKEN <> ";" then ERROR (no ; at the end of block); GET_TOKEN(); end; end;
PROC-DECL Procedure procedure-declaration ::= { "procedure" identparam-block ";" block ";" }. procedure PROC-DECL (level); begin while TOKEN = "procedure" do begin GET_TOKEN(); if TOKEN <> IDENT then ERROR (missing procedure declaration); GET_TOKEN(); num_params = PARAM-BLOCK(level); ENTER(procedure, ident, num_params); if TOKEN <> ";" then ERROR (procedure declaration must end with ;); GET_TOKEN(); BLOCK(level+1, num_params); if TOKEN <> ";" then ERROR (no ; at the end of block); GET_TOKEN(); end; end;
PARAM-BLOCK Procedure param-block ::= "(" [ ident { "," ident} ] ")". • procedure PARAM-BLOCK(level); • begin • intparams = 0; • if TOKEN <> "(" then ERROR(); • GET_TOKEN(); • if TOKEN == IDENT then begin • params++; • param_addr = 4 + params; • ENTER(int, ident, param_addr); • GET_TOKEN(); • while TOKEN == "," do begin • GET_TOKEN(); • if TOKEN <> IDENT then ERROR(); • params++; • param_addr = 4 + params; • ENTER(int, ident, param_addr); • GET_TOKEN(); • end • end • if TOKEN <> ")" then ERROR(); • GET_TOKEN(); • return params; • end
STATEMENT Procedure statement ::= … | "call" ident | … procedure STATEMENT(level); … else if TOKEN == "call" then begin GET_TOKEN(); IF TOKEN <> IDENT then ERROR(); GET_TOKEN(); end …
STATEMENT Procedure statement ::= … | "call" identparam-list | … procedure STATEMENT(level, ar_size); … else if TOKEN == "call" then begin GET_TOKEN(); IF TOKEN <> IDENT then ERROR(); GET_TOKEN(); PARAM-LIST(level, ar_size); end …
PARAM-LIST Procedure param-list ::= "(" [ expression { "," expression} ] ")". • procedure PARAM-LIST(level, ar_size); • begin • if TOKEN <> "(" then ERROR(); • GET_TOKEN(); • if TOKEN <> ")" then begin • EXPRESSION(); • while TOKEN == "," do begin • GET_TOKEN(); • EXPRESSION(); • end • end • if TOKEN <> ")" then ERROR(); • GET_TOKEN(); • end
BLOCK Procedure procedure BLOCK(level, num_params); begin ar_size = 4 + num_params; jmpaddr = gen(JMP, 0, 0); if TOKEN = “const” then CONST-DECL(level); if TOKEN = “var” then VAR-DECL(level, &ar_size); if TOKEN = “procedure” then PROC-DECL(level); code[jmpaddr].addr = NEXT_CODE_ADDR; gen(INC, 0, ar_size); STATEMENT(level, ar_size); gen(OPR, 0, 0); end;
PARAM-LIST Procedure procedure PARAM-LIST(level, ar_size); Begin intparam_count = 0; if TOKEN <> "(" then ERROR(); GET_TOKEN(); if TOKEN <> ")" then begin EXPRESSION(); param_count++; gen(STO, curreg, 0, ar_size+4+param_count); curreg--; while TOKEN == "," do begin GET_TOKEN(); EXPRESSION(); param_count++; gen(STO, curreg, 0, ar_size+4+param_count); curreg--; end end if TOKEN <> ")" then ERROR(); GET_TOKEN(); return param_count; end PARAM-LIST must initialize the parameters before we call the procedure. EXPRESSION() gets the value for the parameter… …and here we store the value in the parameter.
PARAM-LIST Procedure procedure PARAM-LIST(level, ar_size); Begin intparam_count = 0; if TOKEN <> "(" then ERROR(); GET_TOKEN(); if TOKEN <> ")" then begin EXPRESSION(); param_count++; gen(STO, curreg, 0, ar_size+4+param_count); curreg--; while TOKEN == "," do begin GET_TOKEN(); EXPRESSION(); param_count++; gen(STO, curreg, 0, ar_size+4+param_count); curreg--; end end if TOKEN <> ")" then ERROR(); GET_TOKEN(); return param_count; end Why???
PARAM-LIST Procedure procedure PARAM-LIST(level, ar_size); Begin intparam_count = 0; if TOKEN <> "(" then ERROR(); GET_TOKEN(); if TOKEN <> ")" then begin EXPRESSION(); param_count++; gen(STO, curreg, 0, ar_size+4+param_count); curreg--; while TOKEN == "," do begin GET_TOKEN(); EXPRESSION(); param_count++; gen(STO, curreg, 0, ar_size+4+param_count); curreg--; end end if TOKEN <> ")" then ERROR(); GET_TOKEN(); return param_count; end Return Value Return Value Current AR Static Link Static Link Dynamic Link Dynamic Link Return Address Return Address Param Slots Param Slots … … Next AR (not created yet!) Int Slots Int Slots … …
Call Code Generation • procedure STATEMENT(level, ar_size); • begin • … • else if TOKEN = "call" then begin • GET_TOKEN(); • if TOKEN <> IDENT then ERROR (missing identifier); • i = find(TOKEN); • if i == 0 then ERROR (); • if symboltype(i) <> PROCEDURE then ERROR(); • param_count = PARAM-LIST(level, ar_size); • if param_count <> symbolparams(i) then ERROR(); • gen(CAL, 0, 0, symboladdr(i)); • GET_TOKEN(); • end • …
Call Code Generation • procedure STATEMENT(level, ar_size); • begin • … • else if TOKEN = "call" then begin • GET_TOKEN(); • if TOKEN <> IDENT then ERROR (missing identifier); • i = find(TOKEN); • if i == 0 then ERROR (); • if symboltype(i) <> PROCEDURE then ERROR(); • param_count = PARAM-LIST(level, ar_size); • if param_count <> symbolparams(i) then ERROR(); • gen(CAL, 0, 0, symboladdr(i)); • GET_TOKEN(); • end • … We must verify that the amount of parameters is exactly the same amount that the procedure declared.