diff options
author | Araq <rumpf_a@web.de> | 2011-10-21 19:07:01 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2011-10-21 19:07:01 +0200 |
commit | 43eace163a03170475b70a12b24c374daef7e43a (patch) | |
tree | d75ab0feb17b0e831980c76d583c621847f16708 | |
parent | a6f90d4cdd397017436d385fbf2b54d80e4c1a77 (diff) | |
download | Nim-43eace163a03170475b70a12b24c374daef7e43a.tar.gz |
further steps for incremental C code generation
-rw-r--r-- | compiler/ccgmerge.nim | 47 | ||||
-rwxr-xr-x | compiler/cgen.nim | 64 | ||||
-rw-r--r-- | compiler/cgendata.nim | 4 |
3 files changed, 74 insertions, 41 deletions
diff --git a/compiler/ccgmerge.nim b/compiler/ccgmerge.nim index 252b11079..3103edc63 100644 --- a/compiler/ccgmerge.nim +++ b/compiler/ccgmerge.nim @@ -220,8 +220,7 @@ proc processMergeInfo(L: var TBaseLexer, m: BModule) = of "labels": m.labels = decodeVInt(L.buf, L.bufpos) else: InternalError("ccgmerge: unkown key: " & k) -proc readMergeInfo*(cfilename: string, m: BModule) = - ## reads the merge information into `m`. +template withCFile(cfilename: string, body: stmt) = var s = LLStreamOpen(cfilename, fmRead) if s == nil: return var L: TBaseLexer @@ -229,9 +228,28 @@ proc readMergeInfo*(cfilename: string, m: BModule) = while true: skipUntilCmd(L) if ^L.bufpos == '\0': break + body + closeBaseLexer(L) + +proc readMergeInfo*(cfilename: string, m: BModule) = + ## reads the merge meta information into `m`. + withCFile(cfilename): var k = readKey(L) - if k == "NIM_merge_INFO": + if k == "NIM_merge_INFO": processMergeInfo(L, m) + break + +type + TMergeSections = object {.pure.} + f: TCFileSections + p: TCProcSections + +proc readMergeSections(cfilename: string, m: var TMergeSections) = + ## reads the merge sections into `m`. + withCFile(cfilename): + var k = readKey(L) + if k == "NIM_merge_INFO": + nil elif ^L.bufpos == '*' and ^(L.bufpos+1) == '/': inc(L.bufpos, 2) # read back into section @@ -240,14 +258,29 @@ proc readMergeInfo*(cfilename: string, m: BModule) = skipWhite(L) var sectionA = CFileSectionNames.find(k) if sectionA > 0 and sectionA <= high(TCFileSection).int: - m.s[TCFileSection(sectionA)] = verbatim + m.f[TCFileSection(sectionA)] = verbatim else: var sectionB = CProcSectionNames.find(k) if sectionB >= 0 and sectionB <= high(TCProcSection).int: - m.initProc.s[TCProcSection(sectionB)] = verbatim + m.p[TCProcSection(sectionB)] = verbatim else: InternalError("ccgmerge: unknown section: " & k) else: - InternalError("ccgmerge: */ expected") - closeBaseLexer(L) + InternalError("ccgmerge: '*/' expected") + +proc mergeRequired*(m: BModule): bool = + for i in low(TCFileSection)..high(TCFileSection): + if m.s[i] != nil: return true + for i in low(TCProcSection)..high(TCProcSection): + if m.initProc.s[i] != nil: return true + +proc mergeFiles*(cfilename: string, m: BModule) = + ## merges the C file with the old version on hard disc. + var old: TMergeSections + readMergeSections(cfilename, old) + # do the merge; old section before new section: + for i in low(TCFileSection)..high(TCFileSection): + m.s[i] = con(old.f[i], m.s[i]) + for i in low(TCProcSection)..high(TCProcSection): + m.initProc.s[i] = con(old.p[i], m.initProc.s[i]) diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 9c0a1d1f7..d621d2791 100755 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -7,8 +7,7 @@ # distribution, for details about the copyright. # -# This is the new C code generator; much cleaner and faster -# than the old one. It also generates better code. +## This module implements the C code generator. import ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp, @@ -855,29 +854,15 @@ proc myOpen(module: PSym, filename: string): PPassContext = proc myOpenCached(module: PSym, filename: string, rd: PRodReader): PPassContext = - if gNimDat == nil: + if gNimDat == nil: registerTypeInfoModule() - # XXX load old nimcache data here! gNimDat.fromCache = true - result = newModule(module, filename) - #if gNimDat == nil: registerTypeInfoModule() - #var cfile = changeFileExt(completeCFilePath(filename), cExt) - #var cfilenoext = changeFileExt(cfile, "") - #addFileToLink(cfilenoext) - #registerModuleToMain(module) - # XXX: this cannot be right here, initalization has to be appended during - # the ``myClose`` call - #result = nil + readMergeInfo(completeCFilePath(gNimDat.cfilename), gNimDat) + + var m = newModule(module, filename) + readMergeInfo(completeCFilePath(m.cfilename), m) + result = m -proc shouldRecompile(code: PRope, cfile, cfilenoext: string): bool = - result = true - if not (optForceFullMake in gGlobalOptions): - var objFile = toObjFile(cfilenoext) - if writeRopeIfNotEqual(code, cfile): return - if ExistsFile(objFile) and os.FileNewer(objFile, cfile): result = false - else: - writeRope(code, cfile) - proc myProcess(b: PPassContext, n: PNode): PNode = result = n if b == nil or passes.skipCodegen(n): return @@ -899,26 +884,41 @@ proc finishModule(m: BModule) = dec(gForwardedProcsCounter, i) setlen(m.forwardedProcs, 0) +proc shouldRecompile(code: PRope, cfile, cfilenoext: string): bool = + result = true + if optForceFullMake notin gGlobalOptions: + var objFile = toObjFile(cfilenoext) + if writeRopeIfNotEqual(code, cfile): return + if ExistsFile(objFile) and os.FileNewer(objFile, cfile): result = false + else: + writeRope(code, cfile) + proc writeModule(m: BModule) = # generate code for the init statements of the module: - genInitCode(m) - finishTypeDescriptions(m) var cfile = completeCFilePath(m.cfilename) var cfilenoext = changeFileExt(cfile, "") + + genInitCode(m) + finishTypeDescriptions(m) if sfMainModule in m.module.flags: # generate main file: app(m.s[cfsProcHeaders], mainModProcs) GenerateThreadVarsSize(m) - var code = genModule(m, cfilenoext) - - when hasTinyCBackend: - if gCmd == cmdRun: - tccgen.compileCCode(ropeToStr(code)) - return - - if not m.fromCache: + + if not m.fromCache or optForceFullMake in gGlobalOptions: + var code = genModule(m, cfilenoext) + when hasTinyCBackend: + if gCmd == cmdRun: + tccgen.compileCCode(ropeToStr(code)) + return + if shouldRecompile(code, changeFileExt(cfile, cExt), cfilenoext): addFileToCompile(cfilenoext) + elif mergeRequired(m): + mergeFiles(cfile, m) + var code = genModule(m, cfilenoext) + writeRope(code, cfile) + addFileToCompile(cfilenoext) addFileToLink(cfilenoext) proc myClose(b: PPassContext, n: PNode): PNode = diff --git a/compiler/cgendata.nim b/compiler/cgendata.nim index a25e7e3db..144ab9304 100644 --- a/compiler/cgendata.nim +++ b/compiler/cgendata.nim @@ -40,12 +40,12 @@ type ctVoid, ctChar, ctBool, ctUInt, ctUInt8, ctUInt16, ctUInt32, ctUInt64, ctInt, ctInt8, ctInt16, ctInt32, ctInt64, ctFloat, ctFloat32, ctFloat64, ctFloat128, ctArray, ctStruct, ctPtr, ctNimStr, ctNimSeq, ctProc, ctCString - TCFileSections = array[TCFileSection, PRope] # represents a generated C file + TCFileSections* = array[TCFileSection, PRope] # represents a generated C file TCProcSection* = enum # the sections a generated C proc consists of cpsLocals, # section of local variables for C proc cpsInit, # section for init of variables for C proc cpsStmts # section of local statements for C proc - TCProcSections = array[TCProcSection, PRope] # represents a generated C proc + TCProcSections* = array[TCProcSection, PRope] # represents a generated C proc BModule* = ref TCGen BProc* = ref TCProc TBlock{.final.} = object |