mirror of
https://github.com/nim-lang/Nim.git
synced 2026-07-17 06:21:18 +00:00
further steps for incremental C code generation
This commit is contained in:
@@ -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])
|
||||
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user