diff options
Diffstat (limited to 'compiler')
-rwxr-xr-x | compiler/ccgthreadvars.nim | 16 | ||||
-rwxr-xr-x | compiler/rodread.nim | 49 | ||||
-rwxr-xr-x | compiler/rodwrite.nim | 16 | ||||
-rwxr-xr-x | compiler/transf.nim | 10 |
4 files changed, 69 insertions, 22 deletions
diff --git a/compiler/ccgthreadvars.nim b/compiler/ccgthreadvars.nim index 7ef084ba8..0f3661010 100755 --- a/compiler/ccgthreadvars.nim +++ b/compiler/ccgthreadvars.nim @@ -8,7 +8,7 @@ # ## Thread var support for crappy architectures that lack native support for -## thread local storage. +## thread local storage. (**Thank you Mac OS X!**) proc emulatedThreadVars(): bool {.inline.} = result = optThreads in gGlobalOptions @@ -23,9 +23,17 @@ proc AccessThreadLocalVar(p: BProc, s: PSym) = appcg(p, cpsInit, "NimTV=(NimThreadVars*)#GetThreadLocalVars();$n") var - nimtv: PRope # nimrod thread vars - nimtvDeps: seq[PType] = @[] - nimtvDeclared = initIntSet() + nimtv: PRope # nimrod thread vars; the struct body + nimtvDeps: seq[PType] = @[] # type deps: every module needs whole struct + nimtvDeclared = initIntSet() # so that every var/field exists only once + # in the struct + +# 'nimtv' is incredibly hard to modularize! Best effort is to store all thread +# vars in a ROD section and with their type deps and load them +# unconditionally... + +# nimtvDeps is VERY hard to cache because it's not a list of IDs nor can it be +# made to be one. proc declareThreadVar(m: BModule, s: PSym, isExtern: bool) = if emulatedThreadVars(): diff --git a/compiler/rodread.nim b/compiler/rodread.nim index 6191218fe..baffac4c4 100755 --- a/compiler/rodread.nim +++ b/compiler/rodread.nim @@ -9,10 +9,11 @@ # This module is responsible for loading of rod files. # -# Reading and writing binary files are really hard to debug. Therefore we use -# a special text format. ROD-files are more efficient to process because -# symbols are only loaded on demand. -# It consists of: +# Reading and writing binary files are really hard to debug. Therefore we use +# a "creative" text/binary hybrid format. ROD-files are more efficient +# to process because symbols are can be loaded on demand. +# +# A ROD file consists of: # # - a header: # NIM:$fileversion\n @@ -28,7 +29,7 @@ # myfile.inc # lib/mymodA # ) -# - a include file dependency section: +# - an include file dependency section: # INCLUDES( # <fileidx> <CRC of myfile.inc>\n # fileidx is the LINE in the file section! # ) @@ -48,6 +49,11 @@ # id-diff idx-diff\n # id-diff idx-diff\n # ) +# +# Since the whole index has to be read in advance, we compress it by +# storing the integer differences to the last entry instead of using the +# real numbers. +# # - an import index consisting of (ID, moduleID)-pairs: # IMPORTS( # id-diff moduleID-diff\n @@ -55,7 +61,12 @@ # ) # - a list of all exported type converters because they are needed for correct # semantic checking: -# CONVERTERS:id id\n # position of the symbol in the DATA section +# CONVERTERS:id id\n # symbol ID +# +# - a list of all (private or exported) methods because they are needed for +# correct dispatcher generation: +# METHODS: id id\n # symbol ID +# # - an AST section that contains the module's AST: # INIT( # idx\n # position of the node in the DATA section @@ -72,8 +83,6 @@ # stops immediately after ``DATA(`` and the rest is only loaded on demand # by using mem'mapped a file. # -# We now also do index compression, because an index always needs to be read. -# import os, options, strutils, nversion, ast, astalgo, msgs, platform, condsyms, @@ -116,7 +125,7 @@ type files: TStringSeq dataIdx: int # offset of start of data section convertersIdx: int # offset of start of converters section - initIdx, interfIdx, compilerProcsIdx: int + initIdx, interfIdx, compilerProcsIdx, methodsIdx: int filename: string index, imports: TIndex readerIndex: int @@ -125,6 +134,7 @@ type syms: TIdTable # already processed symbols memfile: TMemFile # unfortunately there is no point in time where we # can close this! XXX + methods*: TSymSeq PRodReader* = ref TRodReader @@ -547,6 +557,9 @@ proc processRodFile(r: PRodReader, crc: TCrc32) = of "CONVERTERS": r.convertersIdx = r.pos + 1 skipSection(r) + of "METHODS": + r.methodsIdx = r.pos + 1 + skipSection(r) of "DATA": r.dataIdx = r.pos + 2 # "(\10" # We do not read the DATA section here! We read the needed objects on @@ -573,6 +586,7 @@ proc newRodReader(modfilename: string, crc: TCrc32, new(result) result.files = @[] result.modDeps = @[] + result.methods = @[] var r = result r.reason = rrNone r.pos = 0 @@ -599,7 +613,7 @@ proc newRodReader(modfilename: string, crc: TCrc32, processRodFile(r, crc) else: result = nil - else: + else: result = nil proc rrGetType(r: PRodReader, id: int, info: TLineInfo): PType = @@ -681,7 +695,8 @@ proc loadInitSection(r: PRodReader): PNode = r.pos = oldPos proc loadConverters(r: PRodReader) = - # We have to ensure that no exported converter is a stub anymore. + # We have to ensure that no exported converter is a stub anymore, and the + # import mechanism takes care of the rest. if r.convertersIdx == 0 or r.dataIdx == 0: InternalError("importConverters") r.pos = r.convertersIdx @@ -689,6 +704,15 @@ proc loadConverters(r: PRodReader) = var d = decodeVInt(r.s, r.pos) discard rrGetSym(r, d, UnknownLineInfo()) if r.s[r.pos] == ' ': inc(r.pos) + +proc loadMethods(r: PRodReader) = + if r.methodsIdx == 0 or r.dataIdx == 0: + InternalError("loadMethods") + r.pos = r.methodsIdx + while r.s[r.pos] > '\x0A': + var d = decodeVInt(r.s, r.pos) + r.methods.add(rrGetSym(r, d, UnknownLineInfo())) + if r.s[r.pos] == ' ': inc(r.pos) proc getModuleIdx(filename: string): int = for i in countup(0, high(gMods)): @@ -752,7 +776,8 @@ proc handleSymbolFile(module: PSym, filename: string): PRodReader = processInterf(result, module) processCompilerProcs(result, module) loadConverters(result) - else: + loadMethods(result) + else: module.id = getID() proc GetCRC*(filename: string): TCrc32 = diff --git a/compiler/rodwrite.nim b/compiler/rodwrite.nim index 719bdde14..b735aee6a 100755 --- a/compiler/rodwrite.nim +++ b/compiler/rodwrite.nim @@ -29,7 +29,7 @@ type interf: string compilerProcs: string index, imports: TIndex - converters: string + converters, methods: string init: string data: string filename: string @@ -85,6 +85,7 @@ proc newRodWriter(modfilename: string, crc: TCrc32, module: PSym): PRodWriter = result.interf = newStringOfCap(2_000) result.compilerProcs = "" result.converters = "" + result.methods = "" result.init = "" result.data = newStringOfCap(12_000) @@ -350,6 +351,9 @@ proc symStack(w: PRodWriter) = if s.kind == skConverter: if w.converters.len != 0: add(w.converters, ' ') encodeVInt(s.id, w.converters) + elif s.kind == skMethod: + if w.methods.len != 0: add(w.methods, ' ') + encodeVInt(s.id, w.methods) elif IiTableGet(w.imports.tab, s.id) == invalidKey: addToIndex(w.imports, s.id, m.id) #if not Contains(debugWritten, s.id): # MessageOut(w.filename); @@ -455,6 +459,10 @@ proc writeRod(w: PRodWriter) = f.write("CONVERTERS:") f.write(w.converters) f.write(rodNL) + + f.write("METHODS:") + f.write(w.methods) + f.write(rodNL) f.write("INIT(" & rodNL) f.write(w.init) @@ -486,10 +494,10 @@ proc process(c: PPassContext, n: PNode): PNode = of nkProcDef, nkMethodDef, nkIteratorDef, nkConverterDef: var s = n.sons[namePos].sym if s == nil: InternalError(n.info, "rodwrite.process") - if (n.sons[codePos].kind != nkEmpty) or (s.magic != mNone) or - not (sfForward in s.flags): + if n.sons[codePos].kind != nkEmpty or s.magic != mNone or + sfForward notin s.flags: addInterfaceSym(w, s) - of nkVarSection: + of nkVarSection: for i in countup(0, sonsLen(n) - 1): var a = n.sons[i] if a.kind == nkCommentStmt: continue diff --git a/compiler/transf.nim b/compiler/transf.nim index 9c67165e3..0fb3dd2c6 100755 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -18,7 +18,7 @@ import intsets, strutils, lists, options, ast, astalgo, trees, treetab, msgs, os, - idents, renderer, types, passes, semfold, magicsys, cgmeth + idents, renderer, types, passes, semfold, magicsys, cgmeth, rodread const genPrefix* = ":tmp" # prefix for generated names @@ -726,7 +726,7 @@ proc processTransf(context: PPassContext, n: PNode): PNode = # Note: For interactive mode we cannot call 'passes.skipCodegen' and skip # this step! We have to rely that the semantic pass transforms too errornous # nodes into an empty node. - if passes.skipCodegen(n): return n + if passes.skipCodegen(n) or context.fromCache: return n var c = PTransf(context) pushTransCon(c, newTransCon(getCurrOwner(c))) result = PNode(transform(c, n)) @@ -739,9 +739,15 @@ proc openTransf(module: PSym, filename: string): PPassContext = n.module = module result = n +proc openTransfCached(module: PSym, filename: string, + rd: PRodReader): PPassContext = + result = openTransf(module, filename) + for m in items(rd.methods): methodDef(m) + proc transfPass(): TPass = initPass(result) result.open = openTransf + result.openCached = openTransfCached result.process = processTransf result.close = processTransf # we need to process generics too! |