YS
Size: a a a
YS
C
C
C
M
M
YS
AT
M
AT
BD
E
JC
JC
АЗ
VY

VY
type t = {
(* Frame unique id (used for equality testing and tracing) *)
id : int;
(* Label at which the function's machine code begins *)
label: Temp.label;
(* Locations of all the formals *)
formals: access list;
(* Number of locals allocated so far *)
mutable locals: int;
(* Instructions required to implement the "view shift" *)
instrs: Instruction.t list;
} [@@deriving show { with_path = false }]
где access это Abstract location of a formal parameter (function argument) or a local variable that may be placed in a frame or in a register:type access =Соответственно, когда я транслирую у меня есть такая абстракция как
(* Memory location at the specific offset from the frame pointer *)
| InFrame of int
(* Register location *)
| InReg of Temp.t
[@@deriving show { with_path = false }]
(* Creates a new location for a formal parameter or
a local variable, given its index and [escape] flag *)
let mk_access i = function
| true -> InFrame ((i + 1) * (-word_size)) (* Escapes -- alloc in frame *)
| false -> InReg (Temp.mk ()) (* Doesn't escape -- use [Temp.t] (register) *)
(* Makes a new stack frame *)
let mk ~label ~formals =
let id = next_id () in
let formals = List.mapi formals ~f:mk_access in
let locals = 0 in
(* Don't know yet what instructions we need,
so just leave it empty for now *)
let instrs = [] in
{ id; label; formals; locals; instrs }
level:type level = {
parent: level option;
frame: Frame.t
} [@@deriving show { with_path = false }]
let new_level ~parent ~label ~formals =
(* The first "formal" is static link (SL) which
is a frame pointer (FP) that we'll use for
calculating the variable address, when the
variable is accessed from a nested level/frame *)
let static_link = true in
let formals = static_link :: formals in
let frame = Frame.mk ~label ~formals in
{ parent; frame }
Т.е. SL всегда первый в списке formals в структуре данных стек-фрейма. Что значит "VARIOUS static link offsets" на стр. 156?follow_sl
(** We need to use static links to access variablesТо вот это вот выражение, представленное формулой
declared at an outer level of static scope.
For example, to access some variable [x] which is declared
somewhere outside of the current level/scope/frame the
generated IR code should look like:
Mem(BinOp(Const k_n, Plus, Mem(BinOp(Const k_n-1, Plus,
...
Mem(BinOp(Const k_1, Plus, Temp fp))))))
where k_1,...,k_n-1 are the various SL offsets in nested functions,
and k_n is the offset of our variable [x] in its own frame.
This function follows the given number of static links (SL) between
the current [Translate.level] of use and the [Translate.level] of definition. *)
val follow : int -> Ir.expr
Mem(k_n + Mem(K_n-1 + ... + Mem(K_1 + FP)))вырождается в
Mem(Mem(...Mem(FP))), где number of
Mem's = of frames between the inner and outer "levels"K_n = K_n-1 = ... K_1 = 0, или я чего-то не понимаю...exp, которую мы ранее по книги определили(* We need the [addr] here to access different frames.
The address of the frame is the same as the
current frame pointer only when accessing the variable
from its own level. When accessing the variable [access] from an
inner-nested function, the frame address must be calculated
using static links, and the result of this calculation will be
the [addr] argument to our [expr] function (Page 156) *)
let expr access ~addr =
let open Ir in
match access with
| InFrame k -> Mem addr @+ Const k
| InReg t -> Temp t
Mem addr @+ Const k ==> Mem (Const 0) @+ addr ==> Mem addr
где addr это всегда Frame 0AK
VY