first steps to C file merge operation for incremental compilation
This commit is contained in:
parent
7ebaf44897
commit
a6f90d4cdd
8 changed files with 441 additions and 118 deletions
|
|
@ -15,7 +15,7 @@ import
|
|||
options, intsets,
|
||||
nversion, nimsets, msgs, crc, bitsets, idents, lists, types, ccgutils, os,
|
||||
times, ropes, math, passes, rodread, wordrecg, treetab, cgmeth,
|
||||
rodutils, renderer, idgen
|
||||
rodutils, renderer, idgen, cgendata, ccgmerge
|
||||
|
||||
when options.hasTinyCBackend:
|
||||
import tccgen
|
||||
|
|
@ -23,96 +23,6 @@ when options.hasTinyCBackend:
|
|||
proc cgenPass*(): TPass
|
||||
# implementation
|
||||
|
||||
type
|
||||
TLabel = PRope # for the C generator a label is just a rope
|
||||
TCFileSection = enum # the sections a generated C file consists of
|
||||
cfsHeaders, # section for C include file headers
|
||||
cfsForwardTypes, # section for C forward typedefs
|
||||
cfsTypes, # section for C typedefs
|
||||
cfsSeqTypes, # section for sequence types only
|
||||
# this is needed for strange type generation
|
||||
# reasons
|
||||
cfsFieldInfo, # section for field information
|
||||
cfsTypeInfo, # section for type information
|
||||
cfsProcHeaders, # section for C procs prototypes
|
||||
cfsData, # section for C constant data
|
||||
cfsVars, # section for C variable declarations
|
||||
cfsProcs, # section for C procs that are not inline
|
||||
cfsTypeInit1, # section 1 for declarations of type information
|
||||
cfsTypeInit2, # section 2 for init of type information
|
||||
cfsTypeInit3, # section 3 for init of type information
|
||||
cfsDebugInit, # section for init of debug information
|
||||
cfsDynLibInit, # section for init of dynamic library binding
|
||||
cfsDynLibDeinit # section for deinitialization of dynamic
|
||||
# libraries
|
||||
TCTypeKind = enum # describes the type kind of a C type
|
||||
ctVoid, ctChar, ctBool, ctUInt, ctUInt8, ctUInt16, ctUInt32, ctUInt64,
|
||||
ctInt, ctInt8, ctInt16, ctInt32, ctInt64, ctFloat, ctFloat32, ctFloat64,
|
||||
ctFloat128, ctArray, ctStruct, ctPtr, ctNimStr, ctNimSeq, ctProc, ctCString
|
||||
TCFileSections = array[TCFileSection, PRope] # represents a generated C file
|
||||
TCProcSection = enum # the sections a generated C proc consists of
|
||||
cpsLocals, # section of local variables for C proc
|
||||
cpsInit, # section for init of variables for C proc
|
||||
cpsStmts # section of local statements for C proc
|
||||
TCProcSections = array[TCProcSection, PRope] # represents a generated C proc
|
||||
BModule = ref TCGen
|
||||
BProc = ref TCProc
|
||||
TBlock{.final.} = object
|
||||
id*: int # the ID of the label; positive means that it
|
||||
# has been used (i.e. the label should be emitted)
|
||||
nestedTryStmts*: int # how many try statements is it nested into
|
||||
|
||||
TCProc{.final.} = object # represents C proc that is currently generated
|
||||
s: TCProcSections # the procs sections; short name for readability
|
||||
prc: PSym # the Nimrod proc that this C proc belongs to
|
||||
BeforeRetNeeded: bool # true iff 'BeforeRet' label for proc is needed
|
||||
ThreadVarAccessed: bool # true if the proc already accessed some threadvar
|
||||
nestedTryStmts: seq[PNode] # in how many nested try statements we are
|
||||
# (the vars must be volatile then)
|
||||
labels: Natural # for generating unique labels in the C proc
|
||||
blocks: seq[TBlock] # nested blocks
|
||||
options: TOptions # options that should be used for code
|
||||
# generation; this is the same as prc.options
|
||||
# unless prc == nil
|
||||
frameLen: int # current length of frame descriptor
|
||||
sendClosure: PType # closure record type that we pass
|
||||
receiveClosure: PType # closure record type that we get
|
||||
module: BModule # used to prevent excessive parameter passing
|
||||
withinLoop: int # > 0 if we are within a loop
|
||||
|
||||
TTypeSeq = seq[PType]
|
||||
TCGen = object of TPassContext # represents a C source file
|
||||
module*: PSym
|
||||
filename*: string
|
||||
s*: TCFileSections # sections of the C file
|
||||
PreventStackTrace: bool # true if stack traces need to be prevented
|
||||
usesThreadVars: bool # true if the module uses a thread var
|
||||
cfilename*: string # filename of the module (including path,
|
||||
# without extension)
|
||||
typeCache*: TIdTable # cache the generated types
|
||||
forwTypeCache*: TIdTable # cache for forward declarations of types
|
||||
declaredThings*: TIntSet # things we have declared in this .c file
|
||||
declaredProtos*: TIntSet # prototypes we have declared in this .c file
|
||||
headerFiles*: TLinkedList # needed headers to include
|
||||
typeInfoMarker*: TIntSet # needed for generating type information
|
||||
initProc*: BProc # code for init procedure
|
||||
typeStack*: TTypeSeq # used for type generation
|
||||
dataCache*: TNodeTable
|
||||
forwardedProcs*: TSymSeq # keep forwarded procs here
|
||||
typeNodes*, nimTypes*: int # used for type info generation
|
||||
typeNodesName*, nimTypesName*: PRope # used for type info generation
|
||||
labels*: natural # for generating unique module-scope names
|
||||
|
||||
var
|
||||
mainModProcs, mainModInit: PRope # parts of the main module
|
||||
gMapping: PRope # the generated mapping file (if requested)
|
||||
gProcProfile: Natural # proc profile counter
|
||||
gGeneratedSyms: TIntSet # set of ID's of generated symbols
|
||||
gPendingModules: seq[BModule] = @[] # list of modules that are not
|
||||
# finished with code generation
|
||||
gForwardedProcsCounter: int = 0
|
||||
gNimDat: BModule # generated global data
|
||||
|
||||
proc ropeff(cformat, llvmformat: string, args: openarray[PRope]): PRope =
|
||||
if gCmd == cmdCompileToLLVM: result = ropef(llvmformat, args)
|
||||
else: result = ropef(cformat, args)
|
||||
|
|
@ -157,15 +67,6 @@ proc fillLoc(a: var TLoc, k: TLocKind, typ: PType, r: PRope, s: TStorageLoc) =
|
|||
a.s = s
|
||||
if a.r == nil: a.r = r
|
||||
|
||||
proc newProc(prc: PSym, module: BModule): BProc =
|
||||
new(result)
|
||||
result.prc = prc
|
||||
result.module = module
|
||||
if prc != nil: result.options = prc.options
|
||||
else: result.options = gOptions
|
||||
result.blocks = @[]
|
||||
result.nestedTryStmts = @[]
|
||||
|
||||
proc isSimpleConst(typ: PType): bool =
|
||||
result = not (skipTypes(typ, abstractVar).kind in
|
||||
{tyTuple, tyObject, tyArray, tyArrayConstr, tySet, tySequence})
|
||||
|
|
@ -864,31 +765,53 @@ proc genInitCode(m: BModule) =
|
|||
# BUT: the generated init code might depend on a current frame, so
|
||||
# declare it nevertheless:
|
||||
getFrameDecl(m.initProc)
|
||||
|
||||
app(prc, genSectionStart(cpsLocals))
|
||||
app(prc, m.initProc.s[cpsLocals])
|
||||
app(prc, genSectionEnd(cpsLocals))
|
||||
|
||||
app(prc, genSectionStart(cfsTypeInit1))
|
||||
app(prc, m.s[cfsTypeInit1])
|
||||
if optStackTrace in m.initProc.options and not m.PreventStackTrace:
|
||||
app(prc, m.initProc.s[cpsLocals])
|
||||
app(prc, m.s[cfsTypeInit1])
|
||||
var procname = CStringLit(m.initProc, prc, m.module.name.s)
|
||||
var filename = CStringLit(m.initProc, prc, toFilename(m.module.info))
|
||||
app(prc, initFrame(m.initProc, procname, filename))
|
||||
else:
|
||||
app(prc, m.initProc.s[cpsLocals])
|
||||
app(prc, m.s[cfsTypeInit1])
|
||||
app(prc, m.s[cfsTypeInit2])
|
||||
app(prc, m.s[cfsTypeInit3])
|
||||
app(prc, m.s[cfsDebugInit])
|
||||
app(prc, m.s[cfsDynLibInit])
|
||||
app(prc, genSectionEnd(cfsTypeInit1))
|
||||
|
||||
for i in cfsTypeInit2..cfsDynLibInit:
|
||||
app(prc, genSectionStart(i))
|
||||
app(prc, m.s[i])
|
||||
app(prc, genSectionEnd(i))
|
||||
|
||||
app(prc, genSectionStart(cpsInit))
|
||||
app(prc, m.initProc.s[cpsInit])
|
||||
app(prc, genSectionEnd(cpsInit))
|
||||
|
||||
app(prc, genSectionStart(cpsStmts))
|
||||
app(prc, m.initProc.s[cpsStmts])
|
||||
if optStackTrace in m.initProc.options and not m.PreventStackTrace:
|
||||
app(prc, deinitFrame(m.initProc))
|
||||
app(prc, genSectionEnd(cpsStmts))
|
||||
appf(prc, "}$n$n")
|
||||
app(m.s[cfsProcs], prc)
|
||||
# we cannot simply add the init proc to ``m.s[cfsProcs]`` anymore because
|
||||
# that would lead to a *nesting* of merge sections which the merger does
|
||||
# not support. So we add it to another special section: ``cfsInitProc``
|
||||
app(m.s[cfsInitProc], prc)
|
||||
|
||||
proc genModule(m: BModule, cfilenoext: string): PRope =
|
||||
result = getFileHeader(cfilenoext)
|
||||
result.app(genMergeInfo(m))
|
||||
|
||||
app(m.s[cfsHeaders], genSectionStart(cfsHeaders))
|
||||
generateHeaders(m)
|
||||
app(m.s[cfsHeaders], genSectionEnd(cfsHeaders))
|
||||
|
||||
generateThreadLocalStorage(m)
|
||||
for i in countup(low(TCFileSection), cfsProcs): app(result, m.s[i])
|
||||
for i in countup(low(TCFileSection), cfsProcs):
|
||||
app(result, genSectionStart(i))
|
||||
app(result, m.s[i])
|
||||
app(result, genSectionEnd(i))
|
||||
app(result, m.s[cfsInitProc])
|
||||
|
||||
proc rawNewModule(module: PSym, filename: string): BModule =
|
||||
new(result)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue