summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2013-04-04 13:05:38 +0200
committerAraq <rumpf_a@web.de>2013-04-04 13:05:38 +0200
commitbeb13ecf621f87dea88912c340698459a63f0737 (patch)
treec46e8fe359ff0946c8f26624299c4b227dade0f3 /compiler
parent2f826b5305d27a5deb004bc91f52640d89c2f603 (diff)
downloadNim-beb13ecf621f87dea88912c340698459a63f0737.tar.gz
rod file viewer for easier debugging of rod files
Diffstat (limited to 'compiler')
-rw-r--r--compiler/nversion.nim2
-rw-r--r--compiler/rodread.nim300
-rw-r--r--compiler/rodwrite.nim3
-rw-r--r--compiler/service.nim2
4 files changed, 289 insertions, 18 deletions
diff --git a/compiler/nversion.nim b/compiler/nversion.nim
index d60a7a445..42b0a5f9e 100644
--- a/compiler/nversion.nim
+++ b/compiler/nversion.nim
@@ -18,5 +18,5 @@ const
   VersionPatch* = 1
   VersionAsString* = $VersionMajor & "." & $VersionMinor & "." & $VersionPatch
 
-  RodFileVersion* = "1210"       # modify this if the rod-format changes!
+  RodFileVersion* = "1211"       # modify this if the rod-format changes!
 
diff --git a/compiler/rodread.nim b/compiler/rodread.nim
index 3db9452c3..84ef0e1fe 100644
--- a/compiler/rodread.nim
+++ b/compiler/rodread.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2012 Andreas Rumpf
+#        (c) Copyright 2013 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -126,7 +126,7 @@ type
     s: cstring               # mmap'ed file contents
     options: TOptions
     reason: TReasonForRecompile
-    modDeps: seq[int32]
+    modDeps: TStringSeq
     files: TStringSeq
     dataIdx: int             # offset of start of data section
     convertersIdx: int       # offset of start of converters section
@@ -370,12 +370,12 @@ proc decodeSym(r: PRodReader, info: TLineInfo): PSym =
     inc(r.pos)
     id = decodeVInt(r.s, r.pos)
     setId(id)
-  else: 
+  else:
     InternalError(info, "decodeSym: no id")
   if r.s[r.pos] == '&': 
     inc(r.pos)
     ident = getIdent(decodeStr(r.s, r.pos))
-  else: 
+  else:
     InternalError(info, "decodeSym: no ident")
   #echo "decoding: {", ident.s
   result = PSym(IdTableGet(r.syms, id))
@@ -384,8 +384,14 @@ proc decodeSym(r: PRodReader, info: TLineInfo): PSym =
     result.id = id
     IdTablePut(r.syms, result, result)
     if debugIds: registerID(result)
-  elif (result.id != id): 
+  elif result.id != id:
     InternalError(info, "decodeSym: wrong id")
+  elif result.kind != skStub:
+    # we already loaded the symbol
+    return
+  else:
+    reset(result[])
+    result.id = id
   result.kind = k
   result.name = ident         # read the rest of the symbol description:
   if r.s[r.pos] == '^': 
@@ -498,7 +504,7 @@ proc processCompilerProcs(r: PRodReader, module: PSym) =
       IdTablePut(r.syms, s, s)
     StrTableAdd(rodCompilerProcs, s)
 
-proc processIndex(r: PRodReader, idx: var TIndex) = 
+proc processIndex(r: PRodReader; idx: var TIndex; outf: TFile = nil) = 
   var key, val, tmp: int
   inc(r.pos, 2)               # skip "(\10"
   inc(r.line)
@@ -508,10 +514,11 @@ proc processIndex(r: PRodReader, idx: var TIndex) =
       inc(r.pos)
       key = idx.lastIdxKey + tmp
       val = decodeVInt(r.s, r.pos) + idx.lastIdxVal
-    else: 
+    else:
       key = idx.lastIdxKey + 1
       val = tmp + idx.lastIdxVal
     IITablePut(idx.tab, key, val)
+    if not outf.isNil: outf.write(key, " ", val, "\n")
     idx.lastIdxKey = key
     idx.lastIdxVal = val
     setID(key)                # ensure that this id will not be used
@@ -601,8 +608,8 @@ proc processRodFile(r: PRodReader, crc: TCrc32) =
       if r.s[r.pos] == ')': inc(r.pos)
     of "DEPS":
       inc(r.pos)              # skip ':'
-      while r.s[r.pos] > '\x0A': 
-        r.modDeps.add int32(decodeVInt(r.s, r.pos))
+      while r.s[r.pos] > '\x0A':
+        r.modDeps.add(r.files[int32(decodeVInt(r.s, r.pos))])
         if r.s[r.pos] == ' ': inc(r.pos)
     of "INTERF": 
       r.interfIdx = r.pos + 2
@@ -673,11 +680,9 @@ proc newRodReader(modfilename: string, crc: TCrc32,
       add(version, r.s[r.pos])
       inc(r.pos)
     if r.s[r.pos] == '\x0A': inc(r.pos)
-    if version == RodFileVersion: 
+    if version != RodFileVersion: 
       # since ROD files are only for caching, no backwards compatibility is
       # needed
-      processRodFile(r, crc)
-    else: 
       result = nil
   else:
     result = nil
@@ -813,6 +818,7 @@ proc checkDep(fileIdx: int32): TReasonForRecompile =
   if r == nil: 
     result = (if ExistsFile(rodfile): rrRodInvalid else: rrRodDoesNotExist)
   else:
+    processRodFile(r, crc)
     result = r.reason
     if result == rrNone: 
       # check modules it depends on
@@ -822,9 +828,9 @@ proc checkDep(fileIdx: int32): TReasonForRecompile =
       var res = checkDep(SystemFileIdx)
       if res != rrNone: result = rrModDeps
       for i in countup(0, high(r.modDeps)): 
-        res = checkDep(r.modDeps[i])
-        if res != rrNone: 
-          result = rrModDeps 
+        res = checkDep(r.modDeps[i].fileInfoIdx)
+        if res != rrNone:
+          result = rrModDeps
           # we cannot break here, because of side-effects of `checkDep`
   if result != rrNone and gVerbosity > 0:
     rawMessage(hintProcessing, reasonToFrmt[result] % filename)
@@ -862,7 +868,9 @@ proc rawLoadStub(s: PSym) =
   var d = IITableGet(rd.index.tab, s.id)
   if d == invalidKey: InternalError("loadStub: invalid key")
   var rs = decodeSymSafePos(rd, d, UnknownLineInfo())
-  if rs != s: 
+  if rs != s:
+    #echo "rs: ", toHex(cast[int](rs.position), int.sizeof * 2),
+    #     "\ns:  ", toHex(cast[int](s.position), int.sizeof * 2)
     InternalError(rs.info, "loadStub: wrong symbol")
   elif rs.id != theId: 
     InternalError(rs.info, "loadStub: wrong ID") 
@@ -897,3 +905,263 @@ proc getBody*(s: PSym): PNode =
   
 InitIdTable(gTypeTable)
 InitStrTable(rodCompilerProcs)
+
+# viewer:
+proc writeNode(f: TFile; n: PNode) =
+  f.write("(")
+  if n != nil:
+    f.write($n.kind)
+    if n.typ != nil:
+      f.write('^')
+      f.write(n.typ.id)
+    case n.kind
+    of nkCharLit..nkInt64Lit: 
+      if n.intVal != 0:
+        f.write('!')
+        f.write(n.intVal)
+    of nkFloatLit..nkFloat64Lit: 
+      if n.floatVal != 0.0: 
+        f.write('!')
+        f.write($n.floatVal)
+    of nkStrLit..nkTripleStrLit:
+      if n.strVal != "": 
+        f.write('!')
+        f.write(n.strVal.escape)
+    of nkIdent:
+      f.write('!')
+      f.write(n.ident.s)
+    of nkSym:
+      f.write('!')
+      f.write(n.sym.id)
+    else:
+      for i in countup(0, sonsLen(n) - 1): 
+        writeNode(f, n.sons[i])
+  f.write(")")
+
+proc writeSym(f: TFile; s: PSym) =
+  if s == nil:
+    f.write("{}\n")
+    return
+  f.write("{")
+  f.write($s.kind)
+  f.write('+')
+  f.write(s.id)
+  f.write('&')
+  f.write(s.name.s)
+  if s.typ != nil:
+    f.write('^')
+    f.write(s.typ.id)
+  if s.owner != nil:
+    f.write('*')
+    f.write(s.owner.id)
+  if s.flags != {}:
+    f.write('$')
+    f.write($s.flags)
+  if s.magic != mNone:
+    f.write('@')
+    f.write($s.magic)
+  if s.options != gOptions: 
+    f.write('!')
+    f.write($s.options)
+  if s.position != 0: 
+    f.write('%')
+    f.write($s.position)
+  if s.offset != -1:
+    f.write('`')
+    f.write($s.offset)
+  if s.constraint != nil:
+    f.write('#')
+    f.writeNode(s.constraint)
+  if s.ast != nil:
+    f.writeNode(s.ast)
+  f.write("}\n")
+
+proc writeType(f: TFile; t: PType) =
+  if t == nil:
+    f.write("[]\n")
+    return
+  f.write('[')
+  f.write($t.kind)
+  f.write('+')
+  f.write($t.id)
+  if t.n != nil: 
+    f.writeNode(t.n)
+  if t.flags != {}:
+    f.write('$')
+    f.write($t.flags)
+  if t.callConv != low(t.callConv): 
+    f.write('?')
+    f.write($t.callConv)
+  if t.owner != nil:
+    f.write('*')
+    f.write($t.owner.id)
+  if t.sym != nil:
+    f.write('&')
+    f.write(t.sym.id)
+  if t.size != -1:
+    f.write('/')
+    f.write($t.size)
+  if t.align != 2:
+    f.write('=')
+    f.write($t.align)
+  if t.containerID != 0: 
+    f.write('@')
+    f.write($t.containerID)
+  for i in countup(0, sonsLen(t) - 1): 
+    if t.sons[i] == nil: 
+      f.write("^()")
+    else:
+      f.write('^') 
+      f.write($t.sons[i].id)
+  f.write("]\n")
+
+proc viewFile(rodfile: string) =
+  var r = newRodReader(rodfile, 0, 0)
+  if r == nil:
+    rawMessage(errGenerated, "cannot open file (or maybe wrong version):" &
+       rodfile)
+    return
+  var outf = system.open(rodfile.changeFileExt(".rod.txt"), fmWrite)
+  while r.s[r.pos] != '\0':
+    let section = rdWord(r)
+    case section
+    of "CRC":
+      inc(r.pos)              # skip ':'
+      outf.writeln("CRC:", $decodeVInt(r.s, r.pos))
+    of "ID": 
+      inc(r.pos)              # skip ':'
+      r.moduleID = decodeVInt(r.s, r.pos)
+      setID(r.moduleID)
+      outf.writeln("ID:", $r.moduleID)
+    of "OPTIONS":
+      inc(r.pos)              # skip ':'
+      r.options = cast[TOptions](int32(decodeVInt(r.s, r.pos)))
+      outf.writeln("OPTIONS:", $r.options)
+    of "GOPTIONS":
+      inc(r.pos)              # skip ':'
+      let dep = cast[TGlobalOptions](int32(decodeVInt(r.s, r.pos)))
+      outf.writeln("GOPTIONS:", $dep)
+    of "CMD":
+      inc(r.pos)              # skip ':'
+      let dep = cast[TCommands](int32(decodeVInt(r.s, r.pos)))
+      outf.writeln("CMD:", $dep)
+    of "DEFINES":
+      inc(r.pos)              # skip ':'
+      var d = 0
+      outf.write("DEFINES:")
+      while r.s[r.pos] > '\x0A':
+        let w = decodeStr(r.s, r.pos)
+        inc(d)
+        outf.write(" ", w)
+        if r.s[r.pos] == ' ': inc(r.pos)
+      outf.write("\n")
+    of "FILES": 
+      inc(r.pos, 2)           # skip "(\10"
+      inc(r.line)
+      outf.write("FILES(\n")
+      while r.s[r.pos] != ')':
+        let relativePath = decodeStr(r.s, r.pos)
+        let resolvedPath = relativePath.findModule
+        let rr = if resolvedPath.len > 0: resolvedPath else: relativePath
+        r.files.add(rr)
+        inc(r.pos)            # skip #10
+        inc(r.line)
+        outf.writeln(rr)
+      if r.s[r.pos] == ')': inc(r.pos)
+      outf.write(")\n")
+    of "INCLUDES": 
+      inc(r.pos, 2)           # skip "(\10"
+      inc(r.line)
+      outf.write("INCLUDES(\n")
+      while r.s[r.pos] != ')': 
+        let w = r.files[decodeVInt(r.s, r.pos)]
+        inc(r.pos)            # skip ' '
+        let inclCrc = decodeVInt(r.s, r.pos)
+        if r.s[r.pos] == '\x0A': 
+          inc(r.pos)
+          inc(r.line)
+        outf.write(w, " ", inclCrc, "\n")
+      if r.s[r.pos] == ')': inc(r.pos)
+      outf.write(")\n")
+    of "DEPS":
+      inc(r.pos)              # skip ':'
+      outf.write("DEPS:")
+      while r.s[r.pos] > '\x0A': 
+        let v = int32(decodeVInt(r.s, r.pos))
+        r.modDeps.add(r.files[v])
+        if r.s[r.pos] == ' ': inc(r.pos)
+        outf.write(" ", r.files[v])
+      outf.write("\n")
+    of "INTERF",  "COMPILERPROCS":
+      inc r.pos, 2
+      if section == "INTERF": r.interfIdx = r.pos
+      else: r.compilerProcsIdx = r.pos
+      outf.write(section, "(\n")
+      while (r.s[r.pos] > '\x0A') and (r.s[r.pos] != ')'):
+        let w = decodeStr(r.s, r.pos)
+        inc(r.pos)
+        let key = decodeVInt(r.s, r.pos)
+        inc(r.pos)                # #10
+        outf.write(w, " ", key, "\n")
+      if r.s[r.pos] == ')': inc r.pos
+      outf.write(")\n")
+    of "INDEX":
+      outf.write(section, "(\n")
+      processIndex(r, r.index, outf)
+      outf.write(")\n")
+    of "IMPORTS":
+      outf.write(section, "(\n")
+      processIndex(r, r.imports, outf)
+      outf.write(")\n")
+    of "CONVERTERS",  "METHODS":
+      inc r.pos
+      if section == "METHODS": r.methodsIdx = r.pos
+      else: r.convertersIdx = r.pos
+      outf.write(section, ":")
+      while r.s[r.pos] > '\x0A': 
+        let d = decodeVInt(r.s, r.pos)
+        outf.write(" ", $d)
+        if r.s[r.pos] == ' ': inc(r.pos)
+      outf.write("\n")
+    of "DATA":
+      inc(r.pos, 2)
+      r.dataIdx = r.pos
+      outf.write("DATA(\n")
+      while r.s[r.pos] != ')':
+        if r.s[r.pos] == '(':
+          outf.writeNode decodeNode(r, UnknownLineInfo())
+          outf.write("\n")
+        elif r.s[r.pos] == '[':
+          outf.writeType decodeType(r, UnknownLineInfo())
+        else:
+          outf.writeSym decodeSym(r, UnknownLineInfo())
+        if r.s[r.pos] == '\x0A':
+          inc(r.pos)
+          inc(r.line)
+      if r.s[r.pos] == ')': inc r.pos
+      outf.write(")\n")
+    of "INIT":
+      outf.write("INIT(\n")
+      inc r.pos, 2
+      r.initIdx = r.pos
+      while r.s[r.pos] > '\x0A' and r.s[r.pos] != ')': 
+        let d = decodeVInt(r.s, r.pos)
+        inc(r.pos)                # #10
+        #let p = r.pos
+        #r.pos = d + r.dataIdx
+        #outf.writeNode decodeNode(r, UnknownLineInfo())
+        #outf.write("\n")
+        #r.pos = p
+      if r.s[r.pos] == ')': inc r.pos
+      outf.write("\n")
+    else:
+      InternalError("invalid section: '" & section &
+                    "' at " & $r.line & " in " & r.filename)
+      skipSection(r)
+    if r.s[r.pos] == '\x0A':
+      inc(r.pos)
+      inc(r.line)
+  outf.close
+
+when isMainModule:
+  viewFile(paramStr(1).addFileExt(rodExt))
diff --git a/compiler/rodwrite.nim b/compiler/rodwrite.nim
index c0a0cc4eb..b64347ba9 100644
--- a/compiler/rodwrite.nim
+++ b/compiler/rodwrite.nim
@@ -205,6 +205,9 @@ proc encodeType(w: PRodWriter, t: PType, result: var string) =
     return
   # we need no surrounding [] here because the type is in a line of its own
   if t.kind == tyForward: InternalError("encodeType: tyForward")
+  # for the new rodfile viewer we use a preceeding [ so that the data section
+  # can easily be disambiguated:
+  add(result, '[')
   encodeVInt(ord(t.kind), result)
   add(result, '+')
   encodeVInt(t.id, result)
diff --git a/compiler/service.nim b/compiler/service.nim
index eaf3693ce..e2de6e5a0 100644
--- a/compiler/service.nim
+++ b/compiler/service.nim
@@ -83,7 +83,7 @@ proc serve*(action: proc (){.nimcall.}) =
     new(stdoutSocket)
     while true:
       accept(server, stdoutSocket)
-      discard stdoutSocket.recvLine(inp)
+      stdoutSocket.readLine(inp)
       execute inp.string
       stdoutSocket.send("\c\L")
       stdoutSocket.close()