proper order of initialization for .global. variables
This commit is contained in:
parent
e941a14767
commit
a64f03230a
7 changed files with 62 additions and 3 deletions
|
|
@ -53,7 +53,7 @@ proc genSingleVar(p: BProc, a: PNode) =
|
||||||
var targetProc = p
|
var targetProc = p
|
||||||
var immediateAsgn = a.sons[2].kind != nkEmpty
|
var immediateAsgn = a.sons[2].kind != nkEmpty
|
||||||
if sfGlobal in v.flags:
|
if sfGlobal in v.flags:
|
||||||
targetProc = p.module.initProc
|
targetProc = p.module.preInitProc
|
||||||
assignGlobalVar(targetProc, v)
|
assignGlobalVar(targetProc, v)
|
||||||
genObjectInit(targetProc, cpsInit, v.typ, v.loc, true)
|
genObjectInit(targetProc, cpsInit, v.typ, v.loc, true)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -859,6 +859,7 @@ proc genInitCode(m: BModule) =
|
||||||
|
|
||||||
app(prc, genSectionStart(cpsLocals))
|
app(prc, genSectionStart(cpsLocals))
|
||||||
app(prc, m.initProc.s[cpsLocals])
|
app(prc, m.initProc.s[cpsLocals])
|
||||||
|
app(prc, m.preInitProc.s[cpsLocals])
|
||||||
app(prc, genSectionEnd(cpsLocals))
|
app(prc, genSectionEnd(cpsLocals))
|
||||||
|
|
||||||
app(prc, genSectionStart(cfsTypeInit1))
|
app(prc, genSectionStart(cfsTypeInit1))
|
||||||
|
|
@ -875,10 +876,12 @@ proc genInitCode(m: BModule) =
|
||||||
app(prc, genSectionEnd(i))
|
app(prc, genSectionEnd(i))
|
||||||
|
|
||||||
app(prc, genSectionStart(cpsInit))
|
app(prc, genSectionStart(cpsInit))
|
||||||
|
app(prc, m.preInitProc.s[cpsInit])
|
||||||
app(prc, m.initProc.s[cpsInit])
|
app(prc, m.initProc.s[cpsInit])
|
||||||
app(prc, genSectionEnd(cpsInit))
|
app(prc, genSectionEnd(cpsInit))
|
||||||
|
|
||||||
app(prc, genSectionStart(cpsStmts))
|
app(prc, genSectionStart(cpsStmts))
|
||||||
|
app(prc, m.preInitProc.s[cpsStmts])
|
||||||
app(prc, m.initProc.s[cpsStmts])
|
app(prc, m.initProc.s[cpsStmts])
|
||||||
if optStackTrace in m.initProc.options and not m.PreventStackTrace:
|
if optStackTrace in m.initProc.options and not m.PreventStackTrace:
|
||||||
app(prc, deinitFrame(m.initProc))
|
app(prc, deinitFrame(m.initProc))
|
||||||
|
|
@ -916,6 +919,7 @@ proc rawNewModule(module: PSym, filename: string): BModule =
|
||||||
result.typeInfoMarker = initIntSet()
|
result.typeInfoMarker = initIntSet()
|
||||||
result.initProc = newProc(nil, result)
|
result.initProc = newProc(nil, result)
|
||||||
result.initProc.options = gOptions
|
result.initProc.options = gOptions
|
||||||
|
result.preInitProc = newProc(nil, result)
|
||||||
initNodeTable(result.dataCache)
|
initNodeTable(result.dataCache)
|
||||||
result.typeStack = @[]
|
result.typeStack = @[]
|
||||||
result.forwardedProcs = @[]
|
result.forwardedProcs = @[]
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,10 @@ type
|
||||||
headerFiles*: TLinkedList # needed headers to include
|
headerFiles*: TLinkedList # needed headers to include
|
||||||
typeInfoMarker*: TIntSet # needed for generating type information
|
typeInfoMarker*: TIntSet # needed for generating type information
|
||||||
initProc*: BProc # code for init procedure
|
initProc*: BProc # code for init procedure
|
||||||
|
preInitProc*: BProc # code executed before the init proc
|
||||||
|
# used for initialization code for
|
||||||
|
# .global. variables
|
||||||
|
# (or instantiated generic variables)
|
||||||
typeStack*: TTypeSeq # used for type generation
|
typeStack*: TTypeSeq # used for type generation
|
||||||
dataCache*: TNodeTable
|
dataCache*: TNodeTable
|
||||||
forwardedProcs*: TSymSeq # keep forwarded procs here
|
forwardedProcs*: TSymSeq # keep forwarded procs here
|
||||||
|
|
|
||||||
|
|
@ -3267,7 +3267,7 @@ but are used to override the settings temporarily. Example:
|
||||||
{.pop.} # restore old settings
|
{.pop.} # restore old settings
|
||||||
|
|
||||||
|
|
||||||
Register pragma
|
register pragma
|
||||||
---------------
|
---------------
|
||||||
The `register`:idx: pragma is for variables only. It declares the variable as
|
The `register`:idx: pragma is for variables only. It declares the variable as
|
||||||
``register``, giving the compiler a hint that the variable should be placed
|
``register``, giving the compiler a hint that the variable should be placed
|
||||||
|
|
@ -3277,6 +3277,22 @@ though and for good reasons: Often they do a better job without it anyway.
|
||||||
In highly specific cases (a dispatch loop of an bytecode interpreter for
|
In highly specific cases (a dispatch loop of an bytecode interpreter for
|
||||||
example) it may provide benefits, though.
|
example) it may provide benefits, though.
|
||||||
|
|
||||||
|
global pragma
|
||||||
|
---------------
|
||||||
|
The `global`:idx pragma can be applied to a variable within a proc to instruct
|
||||||
|
the compiler to store it in a global location and initialize it once at program
|
||||||
|
startup.
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
proc isHexNumber(s: string): bool =
|
||||||
|
var pattern {.global.} = re"[0-9a-fA-F]+"
|
||||||
|
result = s.match(pattern)
|
||||||
|
|
||||||
|
When used within a generic proc, a separate unique global variable will be
|
||||||
|
created for each instantiation of the proc. The order of initialization of
|
||||||
|
the created global variables within a module is not defined, but all of them
|
||||||
|
will be initialized after any top-level variables in their originating module
|
||||||
|
and before any variable in a module that imports it.
|
||||||
|
|
||||||
DeadCodeElim pragma
|
DeadCodeElim pragma
|
||||||
-------------------
|
-------------------
|
||||||
|
|
|
||||||
15
tests/run/globalaux.nim
Normal file
15
tests/run/globalaux.nim
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
type
|
||||||
|
TObj*[T] = object
|
||||||
|
val*: T
|
||||||
|
|
||||||
|
var
|
||||||
|
totalGlobals* = 0
|
||||||
|
|
||||||
|
proc makeObj[T](x: T): TObj[T] =
|
||||||
|
totalGlobals += 1
|
||||||
|
result.val = x
|
||||||
|
|
||||||
|
proc globalInstance*[T]: var TObj[T] =
|
||||||
|
var g {.global.} = when T is int: makeObj(10) else: makeObj("hello")
|
||||||
|
result = g
|
||||||
|
|
||||||
4
tests/run/globalaux2.nim
Normal file
4
tests/run/globalaux2.nim
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
import globalaux
|
||||||
|
|
||||||
|
echo "in globalaux2: ", globalInstance[int]().val
|
||||||
|
|
||||||
16
tests/run/tglobal.nim
Normal file
16
tests/run/tglobal.nim
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
discard """
|
||||||
|
file: "toop1.nim"
|
||||||
|
output: "in globalaux2: 10\ntotal globals: 2\nint value: 100\nstring value: second"
|
||||||
|
"""
|
||||||
|
|
||||||
|
import globalaux, globalaux2
|
||||||
|
|
||||||
|
echo "total globals: ", totalGlobals
|
||||||
|
|
||||||
|
globalInstance[int]().val = 100
|
||||||
|
echo "int value: ", globalInstance[int]().val
|
||||||
|
|
||||||
|
globalInstance[string]().val = "first"
|
||||||
|
globalInstance[string]().val = "second"
|
||||||
|
echo "string value: ", globalInstance[string]().val
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue