diff options
author | Araq <rumpf_a@web.de> | 2013-04-04 13:05:38 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2013-04-04 13:05:38 +0200 |
commit | beb13ecf621f87dea88912c340698459a63f0737 (patch) | |
tree | c46e8fe359ff0946c8f26624299c4b227dade0f3 /compiler/rodread.nim | |
parent | 2f826b5305d27a5deb004bc91f52640d89c2f603 (diff) | |
download | Nim-beb13ecf621f87dea88912c340698459a63f0737.tar.gz |
rod file viewer for easier debugging of rod files
Diffstat (limited to 'compiler/rodread.nim')
-rw-r--r-- | compiler/rodread.nim | 300 |
1 files changed, 284 insertions, 16 deletions
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)) |