cgendata.nim 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. #
  2. #
  3. # The Nim Compiler
  4. # (c) Copyright 2012 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. ## This module contains the data structures for the C code generation phase.
  10. import
  11. ast, astalgo, ropes, passes, options, intsets, platform, sighashes,
  12. tables, ndi, lineinfos, pathutils
  13. from modulegraphs import ModuleGraph, PPassContext
  14. type
  15. TLabel* = Rope # for the C generator a label is just a rope
  16. TCFileSection* = enum # the sections a generated C file consists of
  17. cfsMergeInfo, # section containing merge information
  18. cfsHeaders, # section for C include file headers
  19. cfsForwardTypes, # section for C forward typedefs
  20. cfsTypes, # section for C typedefs
  21. cfsSeqTypes, # section for sequence types only
  22. # this is needed for strange type generation
  23. # reasons
  24. cfsFieldInfo, # section for field information
  25. cfsTypeInfo, # section for type information
  26. cfsProcHeaders, # section for C procs prototypes
  27. cfsVars, # section for C variable declarations
  28. cfsData, # section for C constant data
  29. cfsProcs, # section for C procs that are not inline
  30. cfsInitProc, # section for the C init proc
  31. cfsTypeInit1, # section 1 for declarations of type information
  32. cfsTypeInit2, # section 2 for init of type information
  33. cfsTypeInit3, # section 3 for init of type information
  34. cfsDebugInit, # section for init of debug information
  35. cfsDynLibInit, # section for init of dynamic library binding
  36. cfsDynLibDeinit # section for deinitialization of dynamic
  37. # libraries
  38. TCTypeKind* = enum # describes the type kind of a C type
  39. ctVoid, ctChar, ctBool,
  40. ctInt, ctInt8, ctInt16, ctInt32, ctInt64,
  41. ctFloat, ctFloat32, ctFloat64, ctFloat128,
  42. ctUInt, ctUInt8, ctUInt16, ctUInt32, ctUInt64,
  43. ctArray, ctPtrToArray, ctStruct, ctPtr, ctNimStr, ctNimSeq, ctProc,
  44. ctCString
  45. TCFileSections* = array[TCFileSection, Rope] # represents a generated C file
  46. TCProcSection* = enum # the sections a generated C proc consists of
  47. cpsLocals, # section of local variables for C proc
  48. cpsInit, # section for init of variables for C proc
  49. cpsStmts # section of local statements for C proc
  50. TCProcSections* = array[TCProcSection, Rope] # represents a generated C proc
  51. BModule* = ref TCGen
  52. BProc* = ref TCProc
  53. TBlock* = object
  54. id*: int # the ID of the label; positive means that it
  55. label*: Rope # generated text for the label
  56. # nil if label is not used
  57. sections*: TCProcSections # the code beloging
  58. isLoop*: bool # whether block is a loop
  59. nestedTryStmts*: int16 # how many try statements is it nested into
  60. nestedExceptStmts*: int16 # how many except statements is it nested into
  61. frameLen*: int16
  62. TCProc = object # represents C proc that is currently generated
  63. prc*: PSym # the Nim proc that this C proc belongs to
  64. beforeRetNeeded*: bool # true iff 'BeforeRet' label for proc is needed
  65. threadVarAccessed*: bool # true if the proc already accessed some threadvar
  66. hasCurFramePointer*: bool # true if _nimCurFrame var needed to recover after
  67. # exception is generated
  68. lastLineInfo*: TLineInfo # to avoid generating excessive 'nimln' statements
  69. currLineInfo*: TLineInfo # AST codegen will make this superfluous
  70. nestedTryStmts*: seq[tuple[n: PNode, inExcept: bool]]
  71. # in how many nested try statements we are
  72. # (the vars must be volatile then)
  73. # bool is true when are in the except part of a try block
  74. finallySafePoints*: seq[Rope] # For correctly cleaning up exceptions when
  75. # using return in finally statements
  76. labels*: Natural # for generating unique labels in the C proc
  77. blocks*: seq[TBlock] # nested blocks
  78. breakIdx*: int # the block that will be exited
  79. # with a regular break
  80. options*: TOptions # options that should be used for code
  81. # generation; this is the same as prc.options
  82. # unless prc == nil
  83. maxFrameLen*: int # max length of frame descriptor
  84. module*: BModule # used to prevent excessive parameter passing
  85. withinLoop*: int # > 0 if we are within a loop
  86. splitDecls*: int # > 0 if we are in some context for C++ that
  87. # requires 'T x = T()' to become 'T x; x = T()'
  88. # (yes, C++ is weird like that)
  89. gcFrameLen*: Natural # for the GC stack marking
  90. prolog*: Rope
  91. sigConflicts*: CountTable[string]
  92. TTypeSeq* = seq[PType]
  93. TypeCache* = Table[SigHash, Rope]
  94. Codegenflag* = enum
  95. preventStackTrace, # true if stack traces need to be prevented
  96. usesThreadVars, # true if the module uses a thread var
  97. frameDeclared, # hack for ROD support so that we don't declare
  98. # a frame var twice in an init proc
  99. isHeaderFile, # C source file is the header file
  100. includesStringh, # C source file already includes ``<string.h>``
  101. objHasKidsValid # whether we can rely on tfObjHasKids
  102. BModuleList* = ref object of RootObj
  103. mainModProcs*, mainModInit*, otherModsInit*, mainDatInit*: Rope
  104. mapping*: Rope # the generated mapping file (if requested)
  105. modules*: seq[BModule] # list of all compiled modules
  106. forwardedProcsCounter*: int
  107. generatedHeader*: BModule
  108. breakPointId*: int
  109. breakpoints*: Rope # later the breakpoints are inserted into the main proc
  110. typeInfoMarker*: TypeCache
  111. config*: ConfigRef
  112. graph*: ModuleGraph
  113. strVersion*, seqVersion*: int # version of the string/seq implementation to use
  114. nimPreciseStackRoots*: int # generate precise stack roots
  115. nimtv*: Rope # Nim thread vars; the struct body
  116. nimtvDeps*: seq[PType] # type deps: every module needs whole struct
  117. nimtvDeclared*: IntSet # so that every var/field exists only once
  118. # in the struct
  119. # 'nimtv' is incredibly hard to modularize! Best
  120. # effort is to store all thread vars in a ROD
  121. # section and with their type deps and load them
  122. # unconditionally...
  123. # nimtvDeps is VERY hard to cache because it's
  124. # not a list of IDs nor can it be made to be one.
  125. TCGen = object of PPassContext # represents a C source file
  126. s*: TCFileSections # sections of the C file
  127. flags*: set[Codegenflag]
  128. module*: PSym
  129. filename*: AbsoluteFile
  130. cfilename*: AbsoluteFile # filename of the module (including path,
  131. # without extension)
  132. tmpBase*: Rope # base for temp identifier generation
  133. typeCache*: TypeCache # cache the generated types
  134. forwTypeCache*: TypeCache # cache for forward declarations of types
  135. declaredThings*: IntSet # things we have declared in this .c file
  136. declaredProtos*: IntSet # prototypes we have declared in this .c file
  137. headerFiles*: seq[string] # needed headers to include
  138. typeInfoMarker*: TypeCache # needed for generating type information
  139. initProc*: BProc # code for init procedure
  140. preInitProc*: BProc # code executed before the init proc
  141. typeStack*: TTypeSeq # used for type generation
  142. dataCache*: TNodeTable
  143. forwardedProcs*: TSymSeq # keep forwarded procs here
  144. typeNodes*, nimTypes*: int # used for type info generation
  145. typeNodesName*, nimTypesName*: Rope # used for type info generation
  146. labels*: Natural # for generating unique module-scope names
  147. extensionLoaders*: array['0'..'9', Rope] # special procs for the
  148. # OpenGL wrapper
  149. injectStmt*: Rope
  150. sigConflicts*: CountTable[SigHash]
  151. g*: BModuleList
  152. ndi*: NdiFile
  153. template config*(m: BModule): ConfigRef = m.g.config
  154. template config*(p: BProc): ConfigRef = p.module.g.config
  155. proc includeHeader*(this: BModule; header: string) =
  156. if not this.headerFiles.contains header:
  157. this.headerFiles.add header
  158. proc s*(p: BProc, s: TCProcSection): var Rope {.inline.} =
  159. # section in the current block
  160. result = p.blocks[p.blocks.len-1].sections[s]
  161. proc procSec*(p: BProc, s: TCProcSection): var Rope {.inline.} =
  162. # top level proc sections
  163. result = p.blocks[0].sections[s]
  164. proc newProc*(prc: PSym, module: BModule): BProc =
  165. new(result)
  166. result.prc = prc
  167. result.module = module
  168. if prc != nil: result.options = prc.options
  169. else: result.options = module.config.options
  170. newSeq(result.blocks, 1)
  171. result.nestedTryStmts = @[]
  172. result.finallySafePoints = @[]
  173. result.sigConflicts = initCountTable[string]()
  174. proc newModuleList*(g: ModuleGraph): BModuleList =
  175. BModuleList(modules: @[], typeInfoMarker: initTable[SigHash, Rope](), config: g.config,
  176. graph: g, nimtvDeps: @[], nimtvDeclared: initIntSet())
  177. iterator cgenModules*(g: BModuleList): BModule =
  178. for i in 0..high(g.modules):
  179. # ultimately, we are iterating over the file ids here.
  180. # some "files" won't have an associated cgen module (like stdin)
  181. # and we must skip over them.
  182. if g.modules[i] != nil: yield g.modules[i]