1#
2#
3#           The Nim Compiler
4#        (c) Copyright 2017 Andreas Rumpf
5#
6#    See the file "copying.txt", included in this
7#    distribution, for details about the copyright.
8#
9
10## The compiler can generate debuginfo to help debuggers in translating back
11## from C/C++/JS code to Nim. The data structure has been designed to produce
12## something useful with Nim's marshal module.
13
14import sighashes
15
16type
17  FilenameMapping* = object
18    package*, file*: string
19    mangled*: SigHash
20  EnumDesc* = object
21    size*: int
22    owner*: SigHash
23    id*: int
24    name*: string
25    values*: seq[(string, int)]
26  DebugInfo* = object
27    version*: int
28    files*: seq[FilenameMapping]
29    enums*: seq[EnumDesc]
30    conflicts*: bool
31
32proc sdbmHash(package, file: string): SigHash =
33  result = 0
34  for i in 0..<package.len:
35    result &= package[i]
36  result &= '.'
37  for i in 0..<file.len:
38    result &= file[i]
39
40proc register*(self: var DebugInfo; package, file: string): SigHash =
41  result = sdbmHash(package, file)
42  for f in self.files:
43    if f.mangled == result:
44      if f.package == package and f.file == file: return
45      self.conflicts = true
46      break
47  self.files.add(FilenameMapping(package: package, file: file, mangled: result))
48
49proc hasEnum*(self: DebugInfo; ename: string; id: int; owner: SigHash): bool =
50  for en in self.enums:
51    if en.owner == owner and en.name == ename and en.id == id: return true
52
53proc registerEnum*(self: var DebugInfo; ed: EnumDesc) =
54  self.enums.add ed
55
56proc init*(self: var DebugInfo) =
57  self.version = 1
58  self.files = @[]
59  self.enums = @[]
60
61var gDebugInfo*: DebugInfo
62debuginfo.init gDebugInfo
63
64import marshal, streams
65
66proc writeDebugInfo*(self: var DebugInfo; file: string) =
67  let s = newFileStream(file, fmWrite)
68  store(s, self)
69  s.close
70
71proc writeDebugInfo*(file: string) = writeDebugInfo(gDebugInfo, file)
72
73proc loadDebugInfo*(self: var DebugInfo; file: string) =
74  let s = newFileStream(file, fmRead)
75  load(s, self)
76  s.close
77
78proc loadDebugInfo*(file: string) = loadDebugInfo(gDebugInfo, file)
79