Global and Variables: Initializations and Guards

CSE 131 Global and Static Variables

● Global variables, as well as both external and internal static variables, will live in either Data (initialized) or BSS (uninitialized)

● Allocate in Data Global or Static Yes Init With Yes Initialized? ● Store const value Variable Constant? during allocation No No ● Allocate in Data ● Allocate in BSS ● Store 0 value ● will during allocation automatically ● Add logic to initialize to 0 when initialize variable program is loaded during run time Global/Static Run-Time Initialization

● For global and external static variables, emit the initialization code all at once at the beginning of main() o As these variables are getting initialized outside of main(), capture/buffer their initialization assembly code and output it at the beginning of main() ● For internal static variables, you emit the initialization code at the same place where the variable is defined within the function ● All testcases will always have a function main() defined ● No global or external static variables will be defined after function main() Initialization Guard

● Ensures that global and static variable initializations occur only ONCE. Ever. ● Necessary since functions may be called more than once, as well as recursively Simple Example (simplified)

.section “.data” ! DATA Section int x = 3; .align 4 static int y; .global x ! mark as ‘.global’ x: .word 3 ! global var ‘x’ function : int foo() { return 17; .section “.bss” ! BSS Section } .align 4 y: .skip 4 ! external static var ‘y’ int z = foo(); .section “.text” ! TEXT Section int w = z; .align 4 .global foo function : void main() foo: { set SAVE.foo, %g1 save %sp, %g1, %sp static int w = z; set 17, %i0 ! return 17 // Other code ret } restore SAVE.foo = -(92 + 0) & -8

.section “.data” ! DATA Section .align 4 .global z ! mark as ‘.global’ z: .word 0 ! global var ‘z’ (dummy val of 0) .global w ! mark as ‘.global’ w: .word 0 ! global var ‘w’ (dummy val of 0)

.section “.data” ! DATA Section .align 4 .glb.init: .word 0 ! initialize global guard .section “.text” ! TEXT Section Simple Example .align 4 .global main (continued) main: set SAVE.main, %g1 save %sp, %g1, %sp int x = 3; set .glb.init, %l0 static int y; ld [%l0], %l1 ! load global guard value cmp %l1, %g0 bne .glb.init_done ! skip global init if done already function : int foo() { nop return 17; } call foo nop int z = foo(); mov %o0, %l0 ! return value of foo() int w = z; set z, %l1 add %g0, %l1, %l1 st %l0, [%l1] ! store foo() into ‘z’ function : void main() { set z, %l0 static int w = z; add %g0, %l0, %l0 // Other code ld [%l0], %l0 } set w, %l1 add %g0, %l1, %l1 st %l0, [%l1] ! store ‘z’ into ‘w’

set 1, %l0 set .glb.init, %l1 st %l0, [%l1] ! store 1 into global guard .glb.init_done: Simple Example (continued)

.section “.data” ! DATA Section .align 4 int x = 3; .main.w: .word 0 ! internal static var ‘w’ (dummy val) static int y; .main.w.init: .word 0 ! initialize ‘main::w’ guard function : int foo() { .section “.text” ! TEXT Section return 17; .align 4 } set .main.w.init, %l0 ld [%l0], %l1 ! load ‘main::w’ guard value int z = foo(); cmp %l1, %g0 int w = z; bne .main.w.init_done ! skip init if done already nop function : void main() set z, %l0 { add %g0, %l0, %l0 static int w = z; ld [%l0], %l0 // Other code set .main.w, %l1 } add %g0, %l1, %l1 st %l0, [%l1] ! store ‘z’ into ‘main::w’

set 1, %l0 set .main.w.init, %l1 st %l0, [%l1] ! store 1 into ‘main::w’ guard .main.w.init_done: // Other code

SAVE.main = (-92 + 0) & -8 SPARC’s “.init” section ● An alternative way of handling global and external static variables with run-time initialization is to leverage the SPARC “.init” section o This section is automatically called before calling the function main and is intended to handle initializations of the program ● If you choose to use this approach, you should only place “call/nop” instructions in the “.init” section, as it has no stack of its own o You should encapsulate the individual variable initialization assembly code into unique assembly functions, and then add the necessary call/nop to those functions within the “.init” section