cgendata.nim 10 KB

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