further steps for incremental C code generation

This commit is contained in:
Araq 2011-10-21 19:07:01 +02:00
commit 43eace163a
3 changed files with 74 additions and 41 deletions

View file

@ -220,8 +220,7 @@ proc processMergeInfo(L: var TBaseLexer, m: BModule) =
of "labels": m.labels = decodeVInt(L.buf, L.bufpos) of "labels": m.labels = decodeVInt(L.buf, L.bufpos)
else: InternalError("ccgmerge: unkown key: " & k) else: InternalError("ccgmerge: unkown key: " & k)
proc readMergeInfo*(cfilename: string, m: BModule) = template withCFile(cfilename: string, body: stmt) =
## reads the merge information into `m`.
var s = LLStreamOpen(cfilename, fmRead) var s = LLStreamOpen(cfilename, fmRead)
if s == nil: return if s == nil: return
var L: TBaseLexer var L: TBaseLexer
@ -229,9 +228,28 @@ proc readMergeInfo*(cfilename: string, m: BModule) =
while true: while true:
skipUntilCmd(L) skipUntilCmd(L)
if ^L.bufpos == '\0': break 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":
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) var k = readKey(L)
if k == "NIM_merge_INFO": if k == "NIM_merge_INFO":
processMergeInfo(L, m) nil
elif ^L.bufpos == '*' and ^(L.bufpos+1) == '/': elif ^L.bufpos == '*' and ^(L.bufpos+1) == '/':
inc(L.bufpos, 2) inc(L.bufpos, 2)
# read back into section # read back into section
@ -240,14 +258,29 @@ proc readMergeInfo*(cfilename: string, m: BModule) =
skipWhite(L) skipWhite(L)
var sectionA = CFileSectionNames.find(k) var sectionA = CFileSectionNames.find(k)
if sectionA > 0 and sectionA <= high(TCFileSection).int: if sectionA > 0 and sectionA <= high(TCFileSection).int:
m.s[TCFileSection(sectionA)] = verbatim m.f[TCFileSection(sectionA)] = verbatim
else: else:
var sectionB = CProcSectionNames.find(k) var sectionB = CProcSectionNames.find(k)
if sectionB >= 0 and sectionB <= high(TCProcSection).int: if sectionB >= 0 and sectionB <= high(TCProcSection).int:
m.initProc.s[TCProcSection(sectionB)] = verbatim m.p[TCProcSection(sectionB)] = verbatim
else: else:
InternalError("ccgmerge: unknown section: " & k) InternalError("ccgmerge: unknown section: " & k)
else: else:
InternalError("ccgmerge: */ expected") InternalError("ccgmerge: '*/' expected")
closeBaseLexer(L)
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])

View file

@ -7,8 +7,7 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
# This is the new C code generator; much cleaner and faster ## This module implements the C code generator.
# than the old one. It also generates better code.
import import
ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp, 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, proc myOpenCached(module: PSym, filename: string,
rd: PRodReader): PPassContext = rd: PRodReader): PPassContext =
if gNimDat == nil: if gNimDat == nil:
registerTypeInfoModule() registerTypeInfoModule()
# XXX load old nimcache data here!
gNimDat.fromCache = true gNimDat.fromCache = true
result = newModule(module, filename) readMergeInfo(completeCFilePath(gNimDat.cfilename), gNimDat)
#if gNimDat == nil: registerTypeInfoModule()
#var cfile = changeFileExt(completeCFilePath(filename), cExt) var m = newModule(module, filename)
#var cfilenoext = changeFileExt(cfile, "") readMergeInfo(completeCFilePath(m.cfilename), m)
#addFileToLink(cfilenoext) result = m
#registerModuleToMain(module)
# XXX: this cannot be right here, initalization has to be appended during
# the ``myClose`` call
#result = nil
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 = proc myProcess(b: PPassContext, n: PNode): PNode =
result = n result = n
if b == nil or passes.skipCodegen(n): return if b == nil or passes.skipCodegen(n): return
@ -899,26 +884,41 @@ proc finishModule(m: BModule) =
dec(gForwardedProcsCounter, i) dec(gForwardedProcsCounter, i)
setlen(m.forwardedProcs, 0) 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) = proc writeModule(m: BModule) =
# generate code for the init statements of the module: # generate code for the init statements of the module:
genInitCode(m)
finishTypeDescriptions(m)
var cfile = completeCFilePath(m.cfilename) var cfile = completeCFilePath(m.cfilename)
var cfilenoext = changeFileExt(cfile, "") var cfilenoext = changeFileExt(cfile, "")
genInitCode(m)
finishTypeDescriptions(m)
if sfMainModule in m.module.flags: if sfMainModule in m.module.flags:
# generate main file: # generate main file:
app(m.s[cfsProcHeaders], mainModProcs) app(m.s[cfsProcHeaders], mainModProcs)
GenerateThreadVarsSize(m) GenerateThreadVarsSize(m)
var code = genModule(m, cfilenoext)
if not m.fromCache or optForceFullMake in gGlobalOptions:
when hasTinyCBackend: var code = genModule(m, cfilenoext)
if gCmd == cmdRun: when hasTinyCBackend:
tccgen.compileCCode(ropeToStr(code)) if gCmd == cmdRun:
return tccgen.compileCCode(ropeToStr(code))
return
if not m.fromCache:
if shouldRecompile(code, changeFileExt(cfile, cExt), cfilenoext): if shouldRecompile(code, changeFileExt(cfile, cExt), cfilenoext):
addFileToCompile(cfilenoext) addFileToCompile(cfilenoext)
elif mergeRequired(m):
mergeFiles(cfile, m)
var code = genModule(m, cfilenoext)
writeRope(code, cfile)
addFileToCompile(cfilenoext)
addFileToLink(cfilenoext) addFileToLink(cfilenoext)
proc myClose(b: PPassContext, n: PNode): PNode = proc myClose(b: PPassContext, n: PNode): PNode =

View file

@ -40,12 +40,12 @@ type
ctVoid, ctChar, ctBool, ctUInt, ctUInt8, ctUInt16, ctUInt32, ctUInt64, ctVoid, ctChar, ctBool, ctUInt, ctUInt8, ctUInt16, ctUInt32, ctUInt64,
ctInt, ctInt8, ctInt16, ctInt32, ctInt64, ctFloat, ctFloat32, ctFloat64, ctInt, ctInt8, ctInt16, ctInt32, ctInt64, ctFloat, ctFloat32, ctFloat64,
ctFloat128, ctArray, ctStruct, ctPtr, ctNimStr, ctNimSeq, ctProc, ctCString 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 TCProcSection* = enum # the sections a generated C proc consists of
cpsLocals, # section of local variables for C proc cpsLocals, # section of local variables for C proc
cpsInit, # section for init of variables for C proc cpsInit, # section for init of variables for C proc
cpsStmts # section of local statements 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 BModule* = ref TCGen
BProc* = ref TCProc BProc* = ref TCProc
TBlock{.final.} = object TBlock{.final.} = object