69 lines
1.7 KiB
Markdown
69 lines
1.7 KiB
Markdown
# Code Generation 1
|
|
|
|
## Organization of Storage
|
|
|
|
* Code Area
|
|
* Static Area
|
|
* Stack Area
|
|
* Heap Area
|
|
|
|
### Stack Management using Register File
|
|
|
|
* Stack pointer (SP): points to the top of the frame
|
|
* Frame Pointer (FP, BP): points to the frame base
|
|
|
|
because stack frame size is not always known at compile time.
|
|
|
|
|
|
### Saving Registers
|
|
|
|
The callee may overwrite useful values in the registers.
|
|
|
|
So caller's useful values should be stored in stack when function-call (`push`), and restored when callee return (`pop`). This role is done by both callee and caller (`caller-saved`, `callee-saved`).
|
|
|
|
* Caller-saved registers
|
|
used to hold **temporary quantities** that need not be preserved across calls.
|
|
* Callee-saved registers
|
|
used to hold **long-lived values** that should be preserved across calls.
|
|
|
|
|
|
So Code before call:
|
|
* push the params.
|
|
* push caller-saved registers
|
|
* push return address (curr `PC`) and jump to callee code
|
|
|
|
Prologue of callee
|
|
* push dynamic link (`FP`)
|
|
* old stack pointer becomes new frame pointer
|
|
* push callee-saved registers
|
|
* push local var
|
|
|
|
Epilogue
|
|
* pop callee-saved registers
|
|
* store return value at appropriate place
|
|
* restore old stack pointer
|
|
* pop old frame pointer
|
|
* pop return addr and jump to that
|
|
|
|
Code after call
|
|
* pop caller-saved registers
|
|
* use return value from appropriate place
|
|
|
|
When accessing stack variable, use offsets from `FP`.
|
|
|
|
## Global Variables or Static Variables
|
|
|
|
Global variables have same references for all scope. They are assigned a **fixed address once** (**statically allocated**).
|
|
|
|
`Code > Static Data > Stack`
|
|
|
|
|
|
## Dynamic Allocation
|
|
|
|
The dynamically allocated value outlives the procedure creating it (unless deleted).
|
|
|
|
`Code > Static Data > Stack -> <- Heap`
|
|
|
|
|
|
|