further steps for incremental C code generation

This commit is contained in:
Araq
2011-10-21 19:07:01 +02:00
parent a6f90d4cdd
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)
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":
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":
processMergeInfo(L, m)
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])

View File

@@ -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 =

View File

@@ -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