cgendata.nim 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  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
  13. from msgs import TLineInfo
  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*{.final.} = 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{.final.} = 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. lastLineInfo*: TLineInfo # to avoid generating excessive 'nimln' statements
  67. currLineInfo*: TLineInfo # AST codegen will make this superfluous
  68. nestedTryStmts*: seq[PNode] # in how many nested try statements we are
  69. # (the vars must be volatile then)
  70. inExceptBlock*: int # are we currently inside an except block?
  71. # leaving such scopes by raise or by return must
  72. # execute any applicable finally blocks
  73. finallySafePoints*: seq[Rope] # For correctly cleaning up exceptions when
  74. # using return in finally statements
  75. labels*: Natural # for generating unique labels in the C proc
  76. blocks*: seq[TBlock] # nested blocks
  77. breakIdx*: int # the block that will be exited
  78. # with a regular break
  79. options*: TOptions # options that should be used for code
  80. # generation; this is the same as prc.options
  81. # unless prc == nil
  82. maxFrameLen*: int # max length of frame descriptor
  83. module*: BModule # used to prevent excessive parameter passing
  84. withinLoop*: int # > 0 if we are within a loop
  85. splitDecls*: int # > 0 if we are in some context for C++ that
  86. # requires 'T x = T()' to become 'T x; x = T()'
  87. # (yes, C++ is weird like that)
  88. gcFrameId*: Natural # for the GC stack marking
  89. gcFrameType*: Rope # the struct {} we put the GC markers into
  90. sigConflicts*: CountTable[string]
  91. TTypeSeq* = seq[PType]
  92. TypeCache* = Table[SigHash, Rope]
  93. Codegenflag* = enum
  94. preventStackTrace, # true if stack traces need to be prevented
  95. usesThreadVars, # true if the module uses a thread var
  96. frameDeclared, # hack for ROD support so that we don't declare
  97. # a frame var twice in an init proc
  98. isHeaderFile, # C source file is the header file
  99. includesStringh, # C source file already includes ``<string.h>``
  100. objHasKidsValid # whether we can rely on tfObjHasKids
  101. BModuleList* = ref object of RootObj
  102. mainModProcs*, mainModInit*, otherModsInit*, mainDatInit*: Rope
  103. mapping*: Rope # the generated mapping file (if requested)
  104. modules*: seq[BModule] # list of all compiled modules
  105. forwardedProcsCounter*: int
  106. generatedHeader*: BModule
  107. breakPointId*: int
  108. breakpoints*: Rope # later the breakpoints are inserted into the main proc
  109. typeInfoMarker*: TypeCache
  110. config*: ConfigRef
  111. TCGen = object of TPassContext # represents a C source file
  112. s*: TCFileSections # sections of the C file
  113. flags*: set[Codegenflag]
  114. module*: PSym
  115. filename*: string
  116. cfilename*: string # filename of the module (including path,
  117. # without extension)
  118. tmpBase*: Rope # base for temp identifier generation
  119. typeCache*: TypeCache # cache the generated types
  120. forwTypeCache*: TypeCache # cache for forward declarations of types
  121. declaredThings*: IntSet # things we have declared in this .c file
  122. declaredProtos*: IntSet # prototypes we have declared in this .c file
  123. headerFiles*: seq[string] # needed headers to include
  124. typeInfoMarker*: TypeCache # needed for generating type information
  125. initProc*: BProc # code for init procedure
  126. postInitProc*: BProc # code to be executed after the init proc
  127. preInitProc*: BProc # code executed before the init proc
  128. typeStack*: TTypeSeq # used for type generation
  129. dataCache*: TNodeTable
  130. forwardedProcs*: TSymSeq # keep forwarded procs here
  131. typeNodes*, nimTypes*: int # used for type info generation
  132. typeNodesName*, nimTypesName*: Rope # used for type info generation
  133. labels*: Natural # for generating unique module-scope names
  134. extensionLoaders*: array['0'..'9', Rope] # special procs for the
  135. # OpenGL wrapper
  136. injectStmt*: Rope
  137. sigConflicts*: CountTable[SigHash]
  138. g*: BModuleList
  139. ndi*: NdiFile
  140. proc includeHeader*(this: BModule; header: string) =
  141. if not this.headerFiles.contains header:
  142. this.headerFiles.add header
  143. proc s*(p: BProc, s: TCProcSection): var Rope {.inline.} =
  144. # section in the current block
  145. result = p.blocks[^1].sections[s]
  146. proc procSec*(p: BProc, s: TCProcSection): var Rope {.inline.} =
  147. # top level proc sections
  148. result = p.blocks[0].sections[s]
  149. proc newProc*(prc: PSym, module: BModule): BProc =
  150. new(result)
  151. result.prc = prc
  152. result.module = module
  153. if prc != nil: result.options = prc.options
  154. else: result.options = gOptions
  155. newSeq(result.blocks, 1)
  156. result.nestedTryStmts = @[]
  157. result.finallySafePoints = @[]
  158. result.sigConflicts = initCountTable[string]()
  159. proc newModuleList*(config: ConfigRef): BModuleList =
  160. BModuleList(modules: @[], typeInfoMarker: initTable[SigHash, Rope](), config: config)
  161. iterator cgenModules*(g: BModuleList): BModule =
  162. for i in 0..high(g.modules):
  163. # ultimately, we are iterating over the file ids here.
  164. # some "files" won't have an associated cgen module (like stdin)
  165. # and we must skip over them.
  166. if g.modules[i] != nil: yield g.modules[i]