cgendata.nim 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  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, ropes, options, intsets,
  12. tables, ndi, lineinfos, pathutils, modulegraphs, sets
  13. type
  14. TLabel* = Rope # for the C generator a label is just a rope
  15. TCFileSection* = enum # the sections a generated C file consists of
  16. cfsMergeInfo, # section containing merge information
  17. cfsHeaders, # section for C include file headers
  18. cfsFrameDefines # section for nim frame macros
  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 (ag ABI checks)
  26. cfsProcHeaders, # section for C procs prototypes
  27. cfsData, # section for C constant data
  28. cfsVars, # section for C variable declarations
  29. cfsProcs, # section for C procs that are not inline
  30. cfsInitProc, # section for the C init proc
  31. cfsDatInitProc, # section for the C datInit proc
  32. cfsTypeInit1, # section 1 for declarations of type information
  33. cfsTypeInit2, # section 2 for init of type information
  34. cfsTypeInit3, # section 3 for init of type information
  35. cfsDebugInit, # section for init of debug information
  36. cfsDynLibInit, # section for init of dynamic library binding
  37. cfsDynLibDeinit # section for deinitialization of dynamic
  38. # libraries
  39. TCTypeKind* = enum # describes the type kind of a C type
  40. ctVoid, ctChar, ctBool,
  41. ctInt, ctInt8, ctInt16, ctInt32, ctInt64,
  42. ctFloat, ctFloat32, ctFloat64, ctFloat128,
  43. ctUInt, ctUInt8, ctUInt16, ctUInt32, ctUInt64,
  44. ctArray, ctPtrToArray, ctStruct, ctPtr, ctNimStr, ctNimSeq, ctProc,
  45. ctCString
  46. TCFileSections* = array[TCFileSection, Rope] # represents a generated C file
  47. TCProcSection* = enum # the sections a generated C proc consists of
  48. cpsLocals, # section of local variables for C proc
  49. cpsInit, # section for init of variables for C proc
  50. cpsStmts # section of local statements for C proc
  51. TCProcSections* = array[TCProcSection, Rope] # represents a generated C proc
  52. BModule* = ref TCGen
  53. BProc* = ref TCProc
  54. TBlock* = object
  55. id*: int # the ID of the label; positive means that it
  56. label*: Rope # generated text for the label
  57. # nil if label is not used
  58. sections*: TCProcSections # the code belonging
  59. isLoop*: bool # whether block is a loop
  60. nestedTryStmts*: int16 # how many try statements is it nested into
  61. nestedExceptStmts*: int16 # how many except statements is it nested into
  62. frameLen*: int16
  63. TCProcFlag* = enum
  64. beforeRetNeeded,
  65. threadVarAccessed,
  66. hasCurFramePointer,
  67. noSafePoints,
  68. nimErrorFlagAccessed,
  69. nimErrorFlagDeclared,
  70. nimErrorFlagDisabled
  71. TCProc = object # represents C proc that is currently generated
  72. prc*: PSym # the Nim proc that this C proc belongs to
  73. flags*: set[TCProcFlag]
  74. lastLineInfo*: TLineInfo # to avoid generating excessive 'nimln' statements
  75. currLineInfo*: TLineInfo # AST codegen will make this superfluous
  76. nestedTryStmts*: seq[tuple[fin: PNode, inExcept: bool, label: Natural]]
  77. # in how many nested try statements we are
  78. # (the vars must be volatile then)
  79. # bool is true when are in the except part of a try block
  80. finallySafePoints*: seq[Rope] # For correctly cleaning up exceptions when
  81. # using return in finally statements
  82. labels*: Natural # for generating unique labels in the C proc
  83. blocks*: seq[TBlock] # nested blocks
  84. breakIdx*: int # the block that will be exited
  85. # with a regular break
  86. options*: TOptions # options that should be used for code
  87. # generation; this is the same as prc.options
  88. # unless prc == nil
  89. module*: BModule # used to prevent excessive parameter passing
  90. withinLoop*: int # > 0 if we are within a loop
  91. splitDecls*: int # > 0 if we are in some context for C++ that
  92. # requires 'T x = T()' to become 'T x; x = T()'
  93. # (yes, C++ is weird like that)
  94. withinTryWithExcept*: int # required for goto based exception handling
  95. withinBlockLeaveActions*: int # complex to explain
  96. sigConflicts*: CountTable[string]
  97. TTypeSeq* = seq[PType]
  98. TypeCache* = Table[SigHash, Rope]
  99. TypeCacheWithOwner* = Table[SigHash, tuple[str: Rope, owner: int32]]
  100. CodegenFlag* = enum
  101. preventStackTrace, # true if stack traces need to be prevented
  102. usesThreadVars, # true if the module uses a thread var
  103. frameDeclared, # hack for ROD support so that we don't declare
  104. # a frame var twice in an init proc
  105. isHeaderFile, # C source file is the header file
  106. includesStringh, # C source file already includes ``<string.h>``
  107. objHasKidsValid # whether we can rely on tfObjHasKids
  108. useAliveDataFromDce # use the `alive: IntSet` field instead of
  109. # computing alive data on our own.
  110. BModuleList* = ref object of RootObj
  111. mainModProcs*, mainModInit*, otherModsInit*, mainDatInit*: Rope
  112. mapping*: Rope # the generated mapping file (if requested)
  113. modules*: seq[BModule] # list of all compiled modules
  114. modulesClosed*: seq[BModule] # list of the same compiled modules, but in the order they were closed
  115. forwardedProcs*: seq[PSym] # proc:s that did not yet have a body
  116. generatedHeader*: BModule
  117. typeInfoMarker*: TypeCacheWithOwner
  118. typeInfoMarkerV2*: TypeCacheWithOwner
  119. config*: ConfigRef
  120. graph*: ModuleGraph
  121. strVersion*, seqVersion*: int # version of the string/seq implementation to use
  122. nimtv*: Rope # Nim thread vars; the struct body
  123. nimtvDeps*: seq[PType] # type deps: every module needs whole struct
  124. nimtvDeclared*: IntSet # so that every var/field exists only once
  125. # in the struct
  126. # 'nimtv' is incredibly hard to modularize! Best
  127. # effort is to store all thread vars in a ROD
  128. # section and with their type deps and load them
  129. # unconditionally...
  130. # nimtvDeps is VERY hard to cache because it's
  131. # not a list of IDs nor can it be made to be one.
  132. TCGen = object of PPassContext # represents a C source file
  133. s*: TCFileSections # sections of the C file
  134. flags*: set[CodegenFlag]
  135. module*: PSym
  136. filename*: AbsoluteFile
  137. cfilename*: AbsoluteFile # filename of the module (including path,
  138. # without extension)
  139. tmpBase*: Rope # base for temp identifier generation
  140. typeCache*: TypeCache # cache the generated types
  141. typeABICache*: HashSet[SigHash] # cache for ABI checks; reusing typeCache
  142. # would be ideal but for some reason enums
  143. # don't seem to get cached so it'd generate
  144. # 1 ABI check per occurence in code
  145. forwTypeCache*: TypeCache # cache for forward declarations of types
  146. declaredThings*: IntSet # things we have declared in this .c file
  147. declaredProtos*: IntSet # prototypes we have declared in this .c file
  148. alive*: IntSet # symbol IDs of alive data as computed by `dce.nim`
  149. headerFiles*: seq[string] # needed headers to include
  150. typeInfoMarker*: TypeCache # needed for generating type information
  151. typeInfoMarkerV2*: TypeCache
  152. initProc*: BProc # code for init procedure
  153. preInitProc*: BProc # code executed before the init proc
  154. hcrCreateTypeInfosProc*: Rope # type info globals are in here when HCR=on
  155. inHcrInitGuard*: bool # We are currently within a HCR reloading guard.
  156. typeStack*: TTypeSeq # used for type generation
  157. dataCache*: TNodeTable
  158. typeNodes*, nimTypes*: int # used for type info generation
  159. typeNodesName*, nimTypesName*: Rope # used for type info generation
  160. labels*: Natural # for generating unique module-scope names
  161. extensionLoaders*: array['0'..'9', Rope] # special procs for the
  162. # OpenGL wrapper
  163. sigConflicts*: CountTable[SigHash]
  164. g*: BModuleList
  165. ndi*: NdiFile
  166. template config*(m: BModule): ConfigRef = m.g.config
  167. template config*(p: BProc): ConfigRef = p.module.g.config
  168. proc includeHeader*(this: BModule; header: string) =
  169. if not this.headerFiles.contains header:
  170. this.headerFiles.add header
  171. proc s*(p: BProc, s: TCProcSection): var Rope {.inline.} =
  172. # section in the current block
  173. result = p.blocks[^1].sections[s]
  174. proc procSec*(p: BProc, s: TCProcSection): var Rope {.inline.} =
  175. # top level proc sections
  176. result = p.blocks[0].sections[s]
  177. proc newProc*(prc: PSym, module: BModule): BProc =
  178. new(result)
  179. result.prc = prc
  180. result.module = module
  181. result.options = if prc != nil: prc.options
  182. else: module.config.options
  183. newSeq(result.blocks, 1)
  184. result.nestedTryStmts = @[]
  185. result.finallySafePoints = @[]
  186. result.sigConflicts = initCountTable[string]()
  187. proc newModuleList*(g: ModuleGraph): BModuleList =
  188. BModuleList(typeInfoMarker: initTable[SigHash, tuple[str: Rope, owner: int32]](),
  189. config: g.config, graph: g, nimtvDeclared: initIntSet())
  190. iterator cgenModules*(g: BModuleList): BModule =
  191. for m in g.modulesClosed:
  192. # iterate modules in the order they were closed
  193. yield m