diff options
-rw-r--r-- | compiler/ccgstmts.nim | 10 | ||||
-rw-r--r-- | compiler/cgen.nim | 34 | ||||
-rw-r--r-- | compiler/cgendata.nim | 1 | ||||
-rw-r--r-- | tests/threads/t8535.nim | 16 |
4 files changed, 45 insertions, 16 deletions
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 81e3fe4a7..a7a2b3fee 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -256,7 +256,15 @@ proc genSingleVar(p: BProc, a: PNode) = # That's why we are doing the construction inside the preInitProc. # genObjectInit relies on the C runtime's guarantees that # global variables will be initialized to zero. - genObjectInit(p.module.preInitProc, cpsInit, v.typ, v.loc, true) + var loc = v.loc + + # When the native TLS is unavailable, a global thread-local variable needs + # one more layer of indirection in order to access the TLS block. + # Only do this for complex types that may need a call to `objectInit` + if sfThread in v.flags and emulatedThreadVars(p.config) and + isComplexValueType(v.typ): + initLocExprSingleUse(p.module.preInitProc, vn, loc) + genObjectInit(p.module.preInitProc, cpsInit, v.typ, loc, true) # Alternative construction using default constructor (which may zeromem): # if sfImportc notin v.flags: constructLoc(p.module.preInitProc, v.loc) if sfExportc in v.flags and p.module.g.generatedHeader != nil: diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 0bf9239b3..01a930de6 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -1136,12 +1136,29 @@ proc genInitCode(m: BModule) = appcg(m, m.s[cfsTypeInit1], "static #TNimType $1[$2];$n", [m.nimTypesName, rope(m.nimTypes)]) + # Give this small function its own scope + addf(prc, "{$N", []) + block: + # Keep a bogus frame in case the code needs one + add(prc, ~"\tTFrame FR_; FR_.len = 0;$N") + + add(prc, genSectionStart(cpsLocals, m.config)) + add(prc, m.preInitProc.s(cpsLocals)) + add(prc, genSectionEnd(cpsLocals, m.config)) + + add(prc, genSectionStart(cpsInit, m.config)) + add(prc, m.preInitProc.s(cpsInit)) + add(prc, genSectionEnd(cpsInit, m.config)) + + add(prc, genSectionStart(cpsStmts, m.config)) + add(prc, m.preInitProc.s(cpsStmts)) + add(prc, genSectionEnd(cpsStmts, m.config)) + addf(prc, "}$N", []) + add(prc, initGCFrame(m.initProc)) add(prc, genSectionStart(cpsLocals, m.config)) - add(prc, m.preInitProc.s(cpsLocals)) add(prc, m.initProc.s(cpsLocals)) - add(prc, m.postInitProc.s(cpsLocals)) add(prc, genSectionEnd(cpsLocals, m.config)) if optStackTrace in m.initProc.options and frameDeclared notin m.flags: @@ -1155,16 +1172,13 @@ proc genInitCode(m: BModule) = add(prc, ~"\tTFrame FR_; FR_.len = 0;$N") add(prc, genSectionStart(cpsInit, m.config)) - add(prc, m.preInitProc.s(cpsInit)) add(prc, m.initProc.s(cpsInit)) - add(prc, m.postInitProc.s(cpsInit)) add(prc, genSectionEnd(cpsInit, m.config)) add(prc, genSectionStart(cpsStmts, m.config)) - add(prc, m.preInitProc.s(cpsStmts)) add(prc, m.initProc.s(cpsStmts)) - add(prc, m.postInitProc.s(cpsStmts)) add(prc, genSectionEnd(cpsStmts, m.config)) + if optStackTrace in m.initProc.options and preventStackTrace notin m.flags: add(prc, deinitFrame(m.initProc)) add(prc, deinitGCFrame(m.initProc)) @@ -1210,11 +1224,6 @@ proc newPreInitProc(m: BModule): BProc = # little hack so that unique temporaries are generated: result.labels = 100_000 -proc newPostInitProc(m: BModule): BProc = - result = newProc(nil, m) - # little hack so that unique temporaries are generated: - result.labels = 200_000 - proc initProcOptions(m: BModule): TOptions = let opts = m.config.options if sfSystemModule in m.module.flags: opts-{optStackTrace} else: opts @@ -1236,7 +1245,6 @@ proc rawNewModule(g: BModuleList; module: PSym, filename: string): BModule = result.initProc = newProc(nil, result) result.initProc.options = initProcOptions(result) result.preInitProc = newPreInitProc(result) - result.postInitProc = newPostInitProc(result) initNodeTable(result.dataCache) result.typeStack = @[] result.forwardedProcs = @[] @@ -1247,7 +1255,6 @@ proc rawNewModule(g: BModuleList; module: PSym, filename: string): BModule = if sfSystemModule in module.flags: incl result.flags, preventStackTrace excl(result.preInitProc.options, optStackTrace) - excl(result.postInitProc.options, optStackTrace) let ndiName = if optCDebug in g.config.globalOptions: changeFileExt(completeCFilePath(g.config, filename), "ndi") else: "" open(result.ndi, ndiName, g.config) @@ -1265,7 +1272,6 @@ proc resetModule*(m: BModule) = m.initProc = newProc(nil, m) m.initProc.options = initProcOptions(m) m.preInitProc = newPreInitProc(m) - m.postInitProc = newPostInitProc(m) initNodeTable(m.dataCache) m.typeStack = @[] m.forwardedProcs = @[] diff --git a/compiler/cgendata.nim b/compiler/cgendata.nim index a526a0f00..56dbd65a2 100644 --- a/compiler/cgendata.nim +++ b/compiler/cgendata.nim @@ -147,7 +147,6 @@ type headerFiles*: seq[string] # needed headers to include typeInfoMarker*: TypeCache # needed for generating type information initProc*: BProc # code for init procedure - postInitProc*: BProc # code to be executed after the init proc preInitProc*: BProc # code executed before the init proc typeStack*: TTypeSeq # used for type generation dataCache*: TNodeTable diff --git a/tests/threads/t8535.nim b/tests/threads/t8535.nim new file mode 100644 index 000000000..a8d69657b --- /dev/null +++ b/tests/threads/t8535.nim @@ -0,0 +1,16 @@ +discard """ + output: "0" +""" + +type + CircAlloc* [Size: static[int] , T] = tuple + baseArray : array[Size,T] + index : uint16 + +type + Job = object of RootObj + +var foo {.threadvar.}: CircAlloc[1,Job] + +when isMainModule: + echo foo.index |