summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2011-10-21 19:07:01 +0200
committerAraq <rumpf_a@web.de>2011-10-21 19:07:01 +0200
commit43eace163a03170475b70a12b24c374daef7e43a (patch)
treed75ab0feb17b0e831980c76d583c621847f16708
parenta6f90d4cdd397017436d385fbf2b54d80e4c1a77 (diff)
downloadNim-43eace163a03170475b70a12b24c374daef7e43a.tar.gz
further steps for incremental C code generation
-rw-r--r--compiler/ccgmerge.nim47
-rwxr-xr-xcompiler/cgen.nim64
-rw-r--r--compiler/cgendata.nim4
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