cgendata.nim 10 KB

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