diff options
author | Araq <rumpf_a@web.de> | 2016-12-05 12:14:24 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2016-12-05 12:14:24 +0100 |
commit | ba38b83dd50c75cc732593910f0a8518703c73d2 (patch) | |
tree | 1b22efcaef68752aa01456706f86553616b52835 | |
parent | 862a32fe85329096eb2af254f8b361cab04c9f3c (diff) | |
download | Nim-ba38b83dd50c75cc732593910f0a8518703c73d2.tar.gz |
refactoring: C codegen with fewer global variables
-rw-r--r-- | compiler/ccgstmts.nim | 14 | ||||
-rw-r--r-- | compiler/ccgtypes.nim | 2 | ||||
-rw-r--r-- | compiler/cgen.nim | 106 | ||||
-rw-r--r-- | compiler/cgendata.nim | 32 | ||||
-rw-r--r-- | compiler/main.nim | 2 | ||||
-rw-r--r-- | compiler/modulegraphs.nim | 1 |
6 files changed, 79 insertions, 78 deletions
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 18987b915..7282e6af5 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -206,8 +206,8 @@ proc genSingleVar(p: BProc, a: PNode) = genObjectInit(p.module.preInitProc, cpsInit, v.typ, v.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 generatedHeader != nil: - genVarPrototypeAux(generatedHeader, v) + if sfExportc in v.flags and p.module.g.generatedHeader != nil: + genVarPrototypeAux(p.module.g.generatedHeader, v) registerGcRoot(p, v) else: let value = a.sons[2] @@ -1024,10 +1024,6 @@ proc genEmit(p: BProc, t: PNode) = genLineDir(p, t) line(p, cpsStmts, s) -var - breakPointId: int = 0 - gBreakpoints: Rope # later the breakpoints are inserted into the main proc - proc genBreakPoint(p: BProc, t: PNode) = var name: string if optEndb in p.options: @@ -1035,10 +1031,10 @@ proc genBreakPoint(p: BProc, t: PNode) = assert(t.sons[1].kind in {nkStrLit..nkTripleStrLit}) name = normalize(t.sons[1].strVal) else: - inc(breakPointId) - name = "bp" & $breakPointId + inc(p.module.g.breakPointId) + name = "bp" & $p.module.g.breakPointId genLineDir(p, t) # BUGFIX - appcg(p.module, gBreakpoints, + appcg(p.module, p.module.g.breakpoints, "#dbgRegisterBreakpoint($1, (NCSTRING)$2, (NCSTRING)$3);$n", [ rope(toLinenumber(t.info)), makeCString(toFilename(t.info)), makeCString(name)]) diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index 0bb700f1c..6a40d4070 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -1084,7 +1084,7 @@ proc genTypeInfo(m: BModule, t: PType): Rope = let owner = t.skipTypes(typedescPtrs).owner.getModule if owner != m.module: # make sure the type info is created in the owner module - discard genTypeInfo(owner.bmod, origType) + discard genTypeInfo(m.g.modules[owner.position], origType) # reference the type info as extern here discard cgsym(m, "TNimType") discard cgsym(m, "TNimNode") diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 7033c89c4..118a10214 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -26,20 +26,13 @@ when options.hasTinyCBackend: # implementation -var - generatedHeader: BModule - proc addForwardedProc(m: BModule, prc: PSym) = m.forwardedProcs.add(prc) - inc(gForwardedProcsCounter) - -proc getCgenModule(s: PSym): BModule = - result = if s.position >= 0 and s.position < gModules.len: gModules[s.position] - else: nil + inc(m.g.forwardedProcsCounter) proc findPendingModule(m: BModule, s: PSym): BModule = var ms = getModule(s) - result = gModules[ms.position] + result = m.g.modules[ms.position] proc emitLazily(s: PSym): bool {.inline.} = result = optDeadCodeElim in gGlobalOptions or @@ -772,8 +765,8 @@ proc requestConstImpl(p: BProc, sym: PSym) = let headerDecl = "extern NIM_CONST $1 $2;$n" % [getTypeDesc(m, sym.loc.t), sym.loc.r] add(m.s[cfsData], headerDecl) - if sfExportc in sym.flags and generatedHeader != nil: - add(generatedHeader.s[cfsData], headerDecl) + if sfExportc in sym.flags and p.module.g.generatedHeader != nil: + add(p.module.g.generatedHeader.s[cfsData], headerDecl) proc isActivated(prc: PSym): bool = prc.typ != nil @@ -784,11 +777,11 @@ proc genProc(m: BModule, prc: PSym) = else: genProcNoForward(m, prc) if {sfExportc, sfCompilerProc} * prc.flags == {sfExportc} and - generatedHeader != nil and lfNoDecl notin prc.loc.flags: - genProcPrototype(generatedHeader, prc) + m.g.generatedHeader != nil and lfNoDecl notin prc.loc.flags: + genProcPrototype(m.g.generatedHeader, prc) if prc.typ.callConv == ccInline: - if not containsOrIncl(generatedHeader.declaredThings, prc.id): - genProcAux(generatedHeader, prc) + if not containsOrIncl(m.g.generatedHeader.declaredThings, prc.id): + genProcAux(m.g.generatedHeader, prc) proc genVarPrototypeAux(m: BModule, sym: PSym) = #assert(sfGlobal in sym.flags) @@ -946,23 +939,24 @@ proc genMainProc(m: BModule) = else: nimMain = PosixNimMain otherMain = PosixCMain - if gBreakpoints != nil: discard cgsym(m, "dbgRegisterBreakpoint") + if m.g.breakpoints != nil: discard cgsym(m, "dbgRegisterBreakpoint") if optEndb in gOptions: - gBreakpoints.add(m.genFilenames) + m.g.breakpoints.add(m.genFilenames) let initStackBottomCall = if platform.targetOS == osStandalone or gSelectedGC == gcNone: "".rope else: ropecg(m, "\t#initStackBottomWith((void *)&inner);$N") inc(m.labels) appcg(m, m.s[cfsProcs], PreMainBody, [ - mainDatInit, gBreakpoints, otherModsInit, + m.g.mainDatInit, m.g.breakpoints, m.g.otherModsInit, if emulatedThreadVars() and platform.targetOS != osStandalone: ropecg(m, "\t#initThreadVarsEmulation();$N") else: "".rope, initStackBottomCall]) - appcg(m, m.s[cfsProcs], nimMain, [mainModInit, initStackBottomCall, rope(m.labels)]) + appcg(m, m.s[cfsProcs], nimMain, + [m.g.mainModInit, initStackBottomCall, rope(m.labels)]) if optNoMain notin gGlobalOptions: appcg(m, m.s[cfsProcs], otherMain, []) @@ -984,19 +978,19 @@ proc getInitName(m: PSym): Rope = proc getDatInitName(m: PSym): Rope = getSomeInitName(m, "DatInit000") -proc registerModuleToMain(m: PSym) = +proc registerModuleToMain(g: BModuleList; m: PSym) = var init = m.getInitName datInit = m.getDatInitName - addf(mainModProcs, "NIM_EXTERNC N_NOINLINE(void, $1)(void);$N", [init]) - addf(mainModProcs, "NIM_EXTERNC N_NOINLINE(void, $1)(void);$N", [datInit]) + addf(g.mainModProcs, "NIM_EXTERNC N_NOINLINE(void, $1)(void);$N", [init]) + addf(g.mainModProcs, "NIM_EXTERNC N_NOINLINE(void, $1)(void);$N", [datInit]) if sfSystemModule notin m.flags: - addf(mainDatInit, "\t$1();$N", [datInit]) + addf(g.mainDatInit, "\t$1();$N", [datInit]) let initCall = "\t$1();$N" % [init] if sfMainModule in m.flags: - add(mainModInit, initCall) + add(g.mainModInit, initCall) else: - add(otherModsInit, initCall) + add(g.otherModsInit, initCall) proc genInitCode(m: BModule) = var initname = getInitName(m.module) @@ -1087,7 +1081,7 @@ proc newPostInitProc(m: BModule): BProc = proc initProcOptions(m: BModule): TOptions = if sfSystemModule in m.module.flags: gOptions-{optStackTrace} else: gOptions -proc rawNewModule(module: PSym, filename: string): BModule = +proc rawNewModule(g: BModuleList; module: PSym, filename: string): BModule = new(result) result.tmpBase = rope("T" & $hashOwner(module) & "_") initLinkedList(result.headerFiles) @@ -1109,6 +1103,7 @@ proc rawNewModule(module: PSym, filename: string): BModule = result.forwardedProcs = @[] result.typeNodesName = getTempName(result) result.nimTypesName = getTempName(result) + result.g = g # no line tracing for the init sections of the system module so that we # don't generate a TFrame which can confuse the stack botton initialization: if sfSystemModule in module.flags: @@ -1147,6 +1142,7 @@ proc resetModule*(m: BModule) = # indicate that this is now cached module # the cache will be invalidated by nullifying gModules m.fromCache = true + m.g = nil # we keep only the "merge info" information for the module # and the properties that can't change: @@ -1160,31 +1156,35 @@ proc resetModule*(m: BModule) = # m.labels # m.FrameDeclared -proc resetCgenModules* = - for m in cgenModules(): resetModule(m) +proc resetCgenModules*(g: BModuleList) = + for m in cgenModules(g): resetModule(m) -proc rawNewModule(module: PSym): BModule = - result = rawNewModule(module, module.position.int32.toFullPath) +proc rawNewModule(g: BModuleList; module: PSym): BModule = + result = rawNewModule(g, module, module.position.int32.toFullPath) -proc newModule(module: PSym): BModule = +proc newModule(g: BModuleList; module: PSym): BModule = # we should create only one cgen module for each module sym - internalAssert getCgenModule(module) == nil - - result = rawNewModule(module) - growCache gModules, module.position - gModules[module.position] = result + result = rawNewModule(g, module) + growCache g.modules, module.position + g.modules[module.position] = result if (optDeadCodeElim in gGlobalOptions): if (sfDeadCodeElim in module.flags): internalError("added pending module twice: " & module.filename) +template injectG() {.dirty.} = + if graph.backend == nil: + graph.backend = newModuleList() + let g = BModuleList(graph.backend) + proc myOpen(graph: ModuleGraph; module: PSym; cache: IdentCache): PPassContext = - result = newModule(module) - if optGenIndex in gGlobalOptions and generatedHeader == nil: + injectG() + result = newModule(g, module) + if optGenIndex in gGlobalOptions and g.generatedHeader == nil: let f = if headerFile.len > 0: headerFile else: gProjectFull - generatedHeader = rawNewModule(module, + g.generatedHeader = rawNewModule(g, module, changeFileExt(completeCFilePath(f), hExt)) - incl generatedHeader.flags, isHeaderFile + incl g.generatedHeader.flags, isHeaderFile proc writeHeader(m: BModule) = var result = getCopyright(m.filename) @@ -1214,8 +1214,9 @@ proc getCFile(m: BModule): string = result = changeFileExt(completeCFilePath(m.cfilename.withPackageName), ext) proc myOpenCached(graph: ModuleGraph; module: PSym, rd: PRodReader): PPassContext = + injectG() assert optSymbolFiles in gGlobalOptions - var m = newModule(module) + var m = newModule(g, module) readMergeInfo(getCFile(m), m) result = m @@ -1236,8 +1237,8 @@ proc finishModule(m: BModule) = internalError(prc.info, "still forwarded: " & prc.name.s) genProcNoForward(m, prc) inc(i) - assert(gForwardedProcsCounter >= i) - dec(gForwardedProcsCounter, i) + assert(m.g.forwardedProcsCounter >= i) + dec(m.g.forwardedProcsCounter, i) setLen(m.forwardedProcs, 0) proc shouldRecompile(code: Rope, cfile: string): bool = @@ -1265,7 +1266,7 @@ proc writeModule(m: BModule, pending: bool) = finishTypeDescriptions(m) if sfMainModule in m.module.flags: # generate main file: - add(m.s[cfsProcHeaders], mainModProcs) + add(m.s[cfsProcHeaders], m.g.mainModProcs) generateThreadVarsSize(m) var code = genModule(m, cfile) @@ -1313,7 +1314,7 @@ proc myClose(b: PPassContext, n: PNode): PNode = m.initProc.options = initProcOptions(m) genStmts(m.initProc, n) # cached modules need to registered too: - registerModuleToMain(m.module) + registerModuleToMain(m.g, m.module) if sfMainModule in m.module.flags: incl m.flags, objHasKidsValid @@ -1321,21 +1322,22 @@ proc myClose(b: PPassContext, n: PNode): PNode = for i in 0..sonsLen(disp)-1: genProcAux(m, disp.sons[i].sym) genMainProc(m) -proc cgenWriteModules* = +proc cgenWriteModules*(backend: RootRef) = + let g = BModuleList(backend) # we need to process the transitive closure because recursive module # deps are allowed (and the system module is processed in the wrong # order anyway) - if generatedHeader != nil: finishModule(generatedHeader) - while gForwardedProcsCounter > 0: - for m in cgenModules(): + if g.generatedHeader != nil: finishModule(g.generatedHeader) + while g.forwardedProcsCounter > 0: + for m in cgenModules(g): if not m.fromCache: finishModule(m) - for m in cgenModules(): + for m in cgenModules(g): if m.fromCache: m.updateCachedModule else: m.writeModule(pending=true) - writeMapping(gMapping) - if generatedHeader != nil: writeHeader(generatedHeader) + writeMapping(g.mapping) + if g.generatedHeader != nil: writeHeader(g.generatedHeader) const cgenPass* = makePass(myOpen, myOpenCached, myProcess, myClose) diff --git a/compiler/cgendata.nim b/compiler/cgendata.nim index 8063315c8..b10d18e67 100644 --- a/compiler/cgendata.nim +++ b/compiler/cgendata.nim @@ -104,6 +104,17 @@ type isHeaderFile, # C source file is the header file includesStringh, # C source file already includes ``<string.h>`` objHasKidsValid # whether we can rely on tfObjHasKids + + + BModuleList* = ref object of RootObj + mainModProcs*, mainModInit*, otherModsInit*, mainDatInit*: Rope + mapping*: Rope # the generated mapping file (if requested) + modules*: seq[BModule] # list of all compiled modules + forwardedProcsCounter*: int + generatedHeader*: BModule + breakPointId*: int + breakpoints*: Rope # later the breakpoints are inserted into the main proc + TCGen = object of TPassContext # represents a C source file s*: TCFileSections # sections of the C file flags*: set[Codegenflag] @@ -131,13 +142,7 @@ type # OpenGL wrapper injectStmt*: Rope sigConflicts*: CountTable[SigHash] - -var - mainModProcs*, mainModInit*, otherModsInit*, mainDatInit*: Rope - # varuious parts of the main module - gMapping*: Rope # the generated mapping file (if requested) - gModules*: seq[BModule] = @[] # list of all compiled modules - gForwardedProcsCounter*: int = 0 + g*: BModuleList proc s*(p: BProc, s: TCProcSection): var Rope {.inline.} = # section in the current block @@ -147,10 +152,6 @@ proc procSec*(p: BProc, s: TCProcSection): var Rope {.inline.} = # top level proc sections result = p.blocks[0].sections[s] -proc bmod*(module: PSym): BModule = - # obtains the BModule for a given module PSym - result = gModules[module.position] - proc newProc*(prc: PSym, module: BModule): BProc = new(result) result.prc = prc @@ -161,10 +162,11 @@ proc newProc*(prc: PSym, module: BModule): BProc = result.nestedTryStmts = @[] result.finallySafePoints = @[] -iterator cgenModules*: BModule = - for i in 0..high(gModules): +proc newModuleList*(): BModuleList = BModuleList(modules: @[]) + +iterator cgenModules*(g: BModuleList): BModule = + for i in 0..high(g.modules): # ultimately, we are iterating over the file ids here. # some "files" won't have an associated cgen module (like stdin) # and we must skip over them. - if gModules[i] != nil: yield gModules[i] - + if g.modules[i] != nil: yield g.modules[i] diff --git a/compiler/main.nim b/compiler/main.nim index 2118078be..4f06acdd1 100644 --- a/compiler/main.nim +++ b/compiler/main.nim @@ -64,7 +64,7 @@ proc commandCompileToC(graph: ModuleGraph; cache: IdentCache) = #registerPass(cleanupPass()) compileProject(graph, cache) - cgenWriteModules() + cgenWriteModules(graph.backend) if gCmd != cmdRun: extccomp.callCCompiler(changeFileExt(gProjectFull, "")) diff --git a/compiler/modulegraphs.nim b/compiler/modulegraphs.nim index 38fd4f89f..d22160b3b 100644 --- a/compiler/modulegraphs.nim +++ b/compiler/modulegraphs.nim @@ -38,6 +38,7 @@ type # first module that included it importStack*: seq[int32] # The current import stack. Used for detecting recursive # module dependencies. + backend*: RootRef # minor hack so that a backend can extend this easily {.this: g.} |