diff options
-rwxr-xr-x | compiler/main.nim | 3 | ||||
-rwxr-xr-x | compiler/sem.nim | 14 | ||||
-rwxr-xr-x | compiler/semdata.nim | 32 | ||||
-rwxr-xr-x | compiler/semexprs.nim | 2 | ||||
-rwxr-xr-x | compiler/seminst.nim | 8 | ||||
-rwxr-xr-x | compiler/semtypinst.nim | 115 |
6 files changed, 65 insertions, 109 deletions
diff --git a/compiler/main.nim b/compiler/main.nim index 06d16ed08..4767c1537 100755 --- a/compiler/main.nim +++ b/compiler/main.nim @@ -282,7 +282,6 @@ proc CommandCompileToC = # rodread.gMods # !! ropes.cache - # !! semdata.gGenericsCache # semthreads.computed? # # suggest.usageSym @@ -397,7 +396,6 @@ proc resetMemory = ResetAllModules() resetRopeCache() resetSysTypes() - gGenericsCache = nil gOwners = @[] rangeDestructorProc = nil for i in low(buckets)..high(buckets): @@ -421,7 +419,6 @@ proc resetMemory = # rodread.gMods # !! ropes.cache - # !! semdata.gGenericsCache # semthreads.computed? # # suggest.usageSym diff --git a/compiler/sem.nim b/compiler/sem.nim index b136cc035..9844d71b0 100755 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -188,15 +188,15 @@ proc semConstBoolExpr(c: PContext, n: PNode): PNode = include semtypes, semtempl, semgnrc, semstmts, semexprs -proc addCodeForGenerics(c: PContext, n: PNode) = - for i in countup(c.generics.lastGenericIdx, Len(c.generics.generics) - 1): - var prc = c.generics.generics[i].inst.sym - if prc.kind in {skProc, skMethod, skConverter} and prc.magic == mNone: - if prc.ast == nil or prc.ast.sons[bodyPos] == nil: +proc addCodeForGenerics(c: PContext, n: PNode) = + for i in countup(c.lastGenericIdx, c.generics.len - 1): + var prc = c.generics[i].inst.sym + if prc.kind in {skProc, skMethod, skConverter} and prc.magic == mNone: + if prc.ast == nil or prc.ast.sons[bodyPos] == nil: InternalError(prc.info, "no code for " & prc.name.s) else: addSon(n, prc.ast) - c.generics.lastGenericIdx = Len(c.generics.generics) + c.lastGenericIdx = c.generics.len proc semExprNoFlags(c: PContext, n: PNode): PNode {.procvar.} = result = semExpr(c, n, {}) @@ -229,7 +229,7 @@ proc myOpenCached(module: PSym, rd: PRodReader): PPassContext = proc SemStmtAndGenerateGenerics(c: PContext, n: PNode): PNode = result = semStmt(c, n) # BUGFIX: process newly generated generics here, not at the end! - if c.generics.lastGenericIdx < Len(c.generics.generics): + if c.lastGenericIdx < c.generics.len: var a = newNodeI(nkStmtList, n.info) addCodeForGenerics(c, a) if sonsLen(a) > 0: diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 54662111b..f5d5a9604 100755 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -39,21 +39,11 @@ type TInstantiationPair* = object genericSym*: PSym inst*: PInstantiation - - # If we generate an instance of a generic, we'd like to re-use that - # instance if possible across module boundaries. However, this is not - # possible if the compilation cache is enabled. So we give up then and use - # the caching of generics only per module, not per project. - TGenericsCache* {.final.} = object - generics*: seq[TInstantiationPair] # a list of the things to compile - lastGenericIdx*: int # used for the generics stack - - PGenericsCache* = ref TGenericsCache + PContext* = ref TContext TContext* = object of TPassContext # a context represents a module module*: PSym # the module sym belonging to the context p*: PProcCon # procedure context - generics*: PGenericsCache # may point to a global or module-local structure friendModule*: PSym # current friend module; may access private data; # this is used so that generic instantiations # can access private object fields @@ -84,9 +74,9 @@ type evalContext*: PEvalContext UnknownIdents*: TIntSet # ids of all unknown identifiers to prevent # naming it multiple times - -var - gGenericsCache*: PGenericsCache # save for modularity + generics*: seq[TInstantiationPair] # pending list of instantiated generics to compile + lastGenericIdx*: int # used for the generics stack + proc makeInstPair*(s: PSym, inst: PInstantiation): TInstantiationPair = result.genericSym = s @@ -96,10 +86,6 @@ proc filename*(c: PContext): string = # the module's filename return c.module.filename -proc newGenericsCache*(): PGenericsCache = - new(result) - result.generics = @[] - proc newContext*(module: PSym): PContext proc lastOptionEntry*(c: PContext): POptionEntry @@ -171,15 +157,7 @@ proc newContext(module: PSym): PContext = result.patterns = @[] result.includedFiles = initIntSet() initStrTable(result.userPragmas) - if optSymbolFiles notin gGlobalOptions: - # re-usage of generic instantiations across module boundaries is - # very nice for code size: - if gGenericsCache == nil: gGenericsCache = newGenericsCache() - result.generics = gGenericsCache - else: - # we have to give up and use a per-module cache for generic instantiations: - result.generics = newGenericsCache() - assert gGenericsCache == nil + result.generics = @[] result.UnknownIdents = initIntSet() proc inclSym(sq: var TSymSeq, s: PSym) = diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index e1d69c0bc..e6123b1bc 100755 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1359,7 +1359,7 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = let oldInUnrolledContext = c.InUnrolledContext let oldInGenericInst = c.InGenericInst let oldProcCon = c.p - c.generics = newGenericsCache() + c.generics = @[] try: result = semExpr(c, n, flags) if msgs.gErrorCounter != oldErrorCount: result = nil diff --git a/compiler/seminst.nim b/compiler/seminst.nim index 0533d62ad..5a818103d 100755 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -104,9 +104,9 @@ proc instantiateBody(c: PContext, n: PNode, result: PSym) = popProcCon(c) proc fixupInstantiatedSymbols(c: PContext, s: PSym) = - for i in countup(0, Len(c.generics.generics) - 1): - if c.generics.generics[i].genericSym.id == s.id: - var oldPrc = c.generics.generics[i].inst.sym + for i in countup(0, c.generics.len - 1): + if c.generics[i].genericSym.id == s.id: + var oldPrc = c.generics[i].inst.sym pushInfoContext(oldPrc.info) openScope(c.tab) var n = oldPrc.ast @@ -166,7 +166,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, var oldPrc = GenericCacheGet(fn, entry[]) if oldPrc == nil: fn.procInstCache.safeAdd(entry) - c.generics.generics.add(makeInstPair(fn, entry)) + c.generics.add(makeInstPair(fn, entry)) if n.sons[pragmasPos].kind != nkEmpty: pragma(c, result, n.sons[pragmasPos], allRoutinePragmas) if isNil(n.sons[bodyPos]): diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index 03b6e3961..26341525c 100755 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -42,6 +42,11 @@ proc searchInstTypes(key: PType): PType = for inst in genericTyp.sym.typeInstCache: if inst.id == key.id: return inst + if inst.sons.len < key.sons.len: + # XXX: This happens for prematurely cached + # types such as TChannel[empty]. Why? + # See the notes for PActor in handleGenericInvokation + return block MatchType: for j in 1 .. high(key.sons): # XXX sameType is not really correct for nested generics? @@ -138,75 +143,51 @@ proc handleGenericInvokation(cl: var TReplTypeVars, t: PType): PType = var body = t.sons[0] if body.kind != tyGenericBody: InternalError(cl.info, "no generic body") var header: PType = nil - when true: - # search for some instantiation here: - result = searchInstTypes(t) - if result != nil: return - for i in countup(1, sonsLen(t) - 1): - var x = t.sons[i] - if x.kind == tyGenericParam: - x = lookupTypeVar(cl, x) - if header == nil: header = copyType(t, t.owner, false) - header.sons[i] = x - #idTablePut(cl.typeMap, body.sons[i-1], x) - if header != nil: - # search again after first pass: - result = searchInstTypes(header) - if result != nil: return - else: - header = copyType(t, t.owner, false) - # ugh need another pass for deeply recursive generic types (e.g. PActor) - # we need to add the candidate here, before it's fully instantiated for - # recursive instantions: - result = newType(tyGenericInst, t.sons[0].owner) - result.rawAddSon(header.sons[0]) - cacheTypeInst(result) - - for i in countup(1, sonsLen(t) - 1): - var x = replaceTypeVarsT(cl, t.sons[i]) - assert x.kind != tyGenericInvokation + # search for some instantiation here: + result = searchInstTypes(t) + if result != nil: return + for i in countup(1, sonsLen(t) - 1): + var x = t.sons[i] + if x.kind == tyGenericParam: + x = lookupTypeVar(cl, x) + if header == nil: header = copyType(t, t.owner, false) header.sons[i] = x - idTablePut(cl.typeMap, body.sons[i-1], x) - - for i in countup(1, sonsLen(t) - 1): - # if one of the params is not concrete, we cannot do anything - # but we already raised an error! - rawAddSon(result, header.sons[i]) - - var newbody = ReplaceTypeVarsT(cl, lastSon(body)) - newbody.flags = newbody.flags + t.flags + body.flags - result.flags = result.flags + newbody.flags - newbody.callConv = body.callConv - newbody.n = ReplaceTypeVarsN(cl, lastSon(body).n) - # This type may be a generic alias and we want to resolve it here. - # One step is enough, because the recursive nature of - # handleGenericInvokation will handle the alias-to-alias-to-alias case - if newbody.isGenericAlias: newbody = newbody.skipGenericAlias - rawAddSon(result, newbody) - checkPartialConstructedType(cl.info, newbody) + #idTablePut(cl.typeMap, body.sons[i-1], x) + if header != nil: + # search again after first pass: + result = searchInstTypes(header) + if result != nil: return else: - for i in countup(1, sonsLen(t) - 1): - if PType(idTableGet(cl.typeMap, t.sons[i])) == nil: debug(t) - var x = replaceTypeVarsT(cl, t.sons[i]) - if t.sons[i].kind == tyGenericParam: - if header == nil: header = copyType(t, t.owner, false) - header.sons[i] = x - assert x.kind != tyGenericInvokation - idTablePut(cl.typeMap, body.sons[i-1], x) - if header == nil: header = t - result = searchInstTypes(cl.c.generics.InstTypes, header) - if result != nil: return - result = newType(tyGenericInst, t.sons[0].owner) - for i in countup(0, sonsLen(t) - 1): - # if one of the params is not concrete, we cannot do anything - # but we already raised an error! - addSon(result, header.sons[i]) - idTablePut(cl.c.generics.InstTypes, header, result) - var newbody = ReplaceTypeVarsT(cl, lastSon(body)) - newbody.flags = newbody.flags + t.flags + body.flags - newbody.n = ReplaceTypeVarsN(cl, lastSon(body).n) - addSon(result, newbody) - checkPartialConstructedType(cl.info, newbody) + header = copyType(t, t.owner, false) + # ugh need another pass for deeply recursive generic types (e.g. PActor) + # we need to add the candidate here, before it's fully instantiated for + # recursive instantions: + result = newType(tyGenericInst, t.sons[0].owner) + result.rawAddSon(header.sons[0]) + cacheTypeInst(result) + + for i in countup(1, sonsLen(t) - 1): + var x = replaceTypeVarsT(cl, t.sons[i]) + assert x.kind != tyGenericInvokation + header.sons[i] = x + idTablePut(cl.typeMap, body.sons[i-1], x) + + for i in countup(1, sonsLen(t) - 1): + # if one of the params is not concrete, we cannot do anything + # but we already raised an error! + rawAddSon(result, header.sons[i]) + + var newbody = ReplaceTypeVarsT(cl, lastSon(body)) + newbody.flags = newbody.flags + t.flags + body.flags + result.flags = result.flags + newbody.flags + newbody.callConv = body.callConv + newbody.n = ReplaceTypeVarsN(cl, lastSon(body).n) + # This type may be a generic alias and we want to resolve it here. + # One step is enough, because the recursive nature of + # handleGenericInvokation will handle the alias-to-alias-to-alias case + if newbody.isGenericAlias: newbody = newbody.skipGenericAlias + rawAddSon(result, newbody) + checkPartialConstructedType(cl.info, newbody) proc ReplaceTypeVarsT*(cl: var TReplTypeVars, t: PType): PType = result = t |