diff options
-rw-r--r-- | compiler/ast.nim | 3 | ||||
-rw-r--r-- | compiler/ic/packed_ast.nim | 31 | ||||
-rw-r--r-- | compiler/ic/to_packed_ast.nim | 160 | ||||
-rw-r--r-- | compiler/magicsys.nim | 50 | ||||
-rw-r--r-- | compiler/modulegraphs.nim | 12 | ||||
-rw-r--r-- | compiler/sem.nim | 2 | ||||
-rw-r--r-- | compiler/semdata.nim | 54 | ||||
-rw-r--r-- | compiler/semexprs.nim | 18 | ||||
-rw-r--r-- | compiler/semfold.nim | 200 | ||||
-rw-r--r-- | compiler/semmagic.nim | 8 | ||||
-rw-r--r-- | compiler/semstmts.nim | 2 | ||||
-rw-r--r-- | compiler/semtypes.nim | 4 | ||||
-rw-r--r-- | compiler/semtypinst.nim | 18 | ||||
-rw-r--r-- | compiler/transf.nim | 4 |
14 files changed, 289 insertions, 277 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index f8e8f1d3b..0c075cb12 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -223,6 +223,7 @@ type nkTupleConstr # a tuple constructor nkModuleRef # for .rod file support: A (moduleId, itemId) pair nkReplayAction # for .rod file support: A replay action + nkNilRodNode # for .rod file support: a 'nil' PNode TNodeKinds* = set[TNodeKind] @@ -923,7 +924,7 @@ type typeInst*: PType # for generic instantiations the tyGenericInst that led to this # type. uniqueId*: ItemId # due to a design mistake, we need to keep the real ID here as it - # required by the --incremental:on mode. + # is required by the --incremental:on mode. TPair* = object key*, val*: RootRef diff --git a/compiler/ic/packed_ast.nim b/compiler/ic/packed_ast.nim index 0758d3b98..708761764 100644 --- a/compiler/ic/packed_ast.nim +++ b/compiler/ic/packed_ast.nim @@ -12,7 +12,7 @@ ## use this representation directly in all the transformations, ## it is superior. -import std / [hashes, tables, strtabs, md5] +import std / [hashes, tables, strtabs] import bitabs import ".." / [ast, options] @@ -27,8 +27,6 @@ type module*: LitId # 0 if it's this module item*: int32 # same as the in-memory representation - TypeId* = PackedItemId - const nilItemId* = PackedItemId(module: LitId(0), item: -1.int32) @@ -51,7 +49,7 @@ type PackedSym* = object kind*: TSymKind name*: LitId - typ*: TypeId + typ*: PackedItemId flags*: TSymFlags magic*: TMagic info*: PackedLineInfo @@ -74,7 +72,7 @@ type callConv*: TCallingConvention #nodekind*: TNodeKind flags*: TTypeFlags - types*: seq[TypeId] + types*: seq[PackedItemId] n*: NodeId methods*: seq[(int, PackedItemId)] #nodeflags*: TNodeFlags @@ -86,7 +84,7 @@ type paddingAtEnd*: int16 lockLevel*: TLockLevel # lock level as required for deadlock checking # not serialized: loc*: TLoc because it is backend-specific - typeInst*: TypeId + typeInst*: PackedItemId nonUniqueId*: int32 PackedNode* = object # 20 bytes @@ -96,17 +94,9 @@ type # for kind in {nkStrLit, nkIdent, nkNumberLit}: LitId # for kind in nkInt32Lit: direct value # for non-atom kinds: the number of nodes (for easy skipping) - typeId*: TypeId + typeId*: PackedItemId info*: PackedLineInfo - ModulePhase* = enum - preLookup, lookedUpTopLevelStmts - - GenericKey* = object - module*: int32 - name*: string - types*: seq[MD5Digest] # is this a joke? - PackedTree* = object ## usually represents a full Nim module nodes*: seq[PackedNode] #sh*: Shared @@ -121,18 +111,11 @@ type floats*: BiTable[BiggestFloat] #config*: ConfigRef -proc hash*(key: GenericKey): Hash = - var h: Hash = 0 - h = h !& hash(key.module) - h = h !& hash(key.name) - h = h !& hash(key.types) - result = !$h - proc `==`*(a, b: SymId): bool {.borrow.} proc hash*(a: SymId): Hash {.borrow.} proc `==`*(a, b: NodePos): bool {.borrow.} -#proc `==`*(a, b: TypeId): bool {.borrow.} +#proc `==`*(a, b: PackedItemId): bool {.borrow.} proc `==`*(a, b: NodeId): bool {.borrow.} proc newTreeFrom*(old: PackedTree): PackedTree = @@ -197,7 +180,7 @@ when false: result = PatchPos tree.nodes.len tree.nodes.add PackedNode(kind: kind, operand: 0, info: info) -proc prepare*(tree: var PackedTree; kind: TNodeKind; flags: TNodeFlags; typeId: TypeId; info: PackedLineInfo): PatchPos = +proc prepare*(tree: var PackedTree; kind: TNodeKind; flags: TNodeFlags; typeId: PackedItemId; info: PackedLineInfo): PatchPos = result = PatchPos tree.nodes.len tree.nodes.add PackedNode(kind: kind, flags: flags, operand: 0, info: info, typeId: typeId) diff --git a/compiler/ic/to_packed_ast.nim b/compiler/ic/to_packed_ast.nim index aa3b447b8..cf1e940d3 100644 --- a/compiler/ic/to_packed_ast.nim +++ b/compiler/ic/to_packed_ast.nim @@ -174,16 +174,16 @@ proc addCompilerProc*(c: var PackedEncoder; m: var PackedModule; s: PSym) = m.compilerProcs.add((nameId, s.itemId.item)) proc toPackedNode*(n: PNode; ir: var PackedTree; c: var PackedEncoder; m: var PackedModule) -proc toPackedSym*(s: PSym; c: var PackedEncoder; m: var PackedModule): PackedItemId -proc toPackedType(t: PType; c: var PackedEncoder; m: var PackedModule): PackedItemId +proc storeSym*(s: PSym; c: var PackedEncoder; m: var PackedModule): PackedItemId +proc storeType(t: PType; c: var PackedEncoder; m: var PackedModule): PackedItemId proc flush(c: var PackedEncoder; m: var PackedModule) = ## serialize any pending types or symbols from the context while true: if c.pendingTypes.len > 0: - discard toPackedType(c.pendingTypes.pop, c, m) + discard storeType(c.pendingTypes.pop, c, m) elif c.pendingSyms.len > 0: - discard toPackedSym(c.pendingSyms.pop, c, m) + discard storeSym(c.pendingSyms.pop, c, m) else: break @@ -210,16 +210,6 @@ proc safeItemId(s: PSym; c: var PackedEncoder; m: var PackedModule): PackedItemI result = PackedItemId(module: toLitId(s.itemId.module.FileIndex, c, m), item: s.itemId.item) -proc addModuleRef(n: PNode; ir: var PackedTree; c: var PackedEncoder; m: var PackedModule) = - ## add a remote symbol reference to the tree - let info = n.info.toPackedInfo(c, m) - ir.nodes.add PackedNode(kind: nkModuleRef, operand: 3.int32, # spans 3 nodes in total - typeId: toPackedType(n.typ, c, m), info: info) - ir.nodes.add PackedNode(kind: nkInt32Lit, info: info, - operand: toLitId(n.sym.itemId.module.FileIndex, c, m).int32) - ir.nodes.add PackedNode(kind: nkInt32Lit, info: info, - operand: n.sym.itemId.item) - proc addMissing(c: var PackedEncoder; p: PSym) = ## consider queuing a symbol for later addition to the packed tree if p != nil and p.itemId.module == c.thisModule: @@ -241,7 +231,36 @@ template storeNode(dest, src, field) = nodeId = emptyNodeId dest.field = nodeId -proc toPackedType(t: PType; c: var PackedEncoder; m: var PackedModule): PackedItemId = +proc storeTypeLater(t: PType; c: var PackedEncoder; m: var PackedModule): PackedItemId = + # We store multiple different trees in m.bodies. For this to work out, we + # cannot immediately store types/syms. We enqueue them instead to ensure + # we only write one tree into m.bodies after the other. + if t.isNil: return nilItemId + + if t.uniqueId.module != c.thisModule: + # XXX Assert here that it already was serialized in the foreign module! + # it is a foreign type: + assert t.uniqueId.module >= 0 + assert t.uniqueId.item > 0 + return PackedItemId(module: toLitId(t.uniqueId.module.FileIndex, c, m), item: t.uniqueId.item) + assert t.itemId.module >= 0 + assert t.uniqueId.item > 0 + result = PackedItemId(module: toLitId(t.itemId.module.FileIndex, c, m), item: t.uniqueId.item) + addMissing(c, t) + +proc storeSymLater(s: PSym; c: var PackedEncoder; m: var PackedModule): PackedItemId = + if s.isNil: return nilItemId + assert s.itemId.module >= 0 + if s.itemId.module != c.thisModule: + # XXX Assert here that it already was serialized in the foreign module! + # it is a foreign symbol: + assert s.itemId.module >= 0 + return PackedItemId(module: toLitId(s.itemId.module.FileIndex, c, m), item: s.itemId.item) + assert s.itemId.module >= 0 + result = PackedItemId(module: toLitId(s.itemId.module.FileIndex, c, m), item: s.itemId.item) + addMissing(c, s) + +proc storeType(t: PType; c: var PackedEncoder; m: var PackedModule): PackedItemId = ## serialize a ptype if t.isNil: return nilItemId @@ -249,6 +268,7 @@ proc toPackedType(t: PType; c: var PackedEncoder; m: var PackedModule): PackedIt # XXX Assert here that it already was serialized in the foreign module! # it is a foreign type: assert t.uniqueId.module >= 0 + assert t.uniqueId.item > 0 return PackedItemId(module: toLitId(t.uniqueId.module.FileIndex, c, m), item: t.uniqueId.item) if not c.typeMarker.containsOrIncl(t.uniqueId.item): @@ -264,9 +284,9 @@ proc toPackedType(t: PType; c: var PackedEncoder; m: var PackedModule): PackedIt c.addMissing s p.attachedOps[op] = s.safeItemId(c, m) - p.typeInst = t.typeInst.toPackedType(c, m) + p.typeInst = t.typeInst.storeType(c, m) for kid in items t.sons: - p.types.add kid.toPackedType(c, m) + p.types.add kid.storeType(c, m) for i, s in items t.methods: c.addMissing s p.methods.add (i, s.safeItemId(c, m)) @@ -279,6 +299,7 @@ proc toPackedType(t: PType; c: var PackedEncoder; m: var PackedModule): PackedIt m.sh.types[t.uniqueId.item] = p assert t.itemId.module >= 0 + assert t.uniqueId.item > 0 result = PackedItemId(module: toLitId(t.itemId.module.FileIndex, c, m), item: t.uniqueId.item) proc toPackedLib(l: PLib; c: var PackedEncoder; m: var PackedModule): PackedLib = @@ -290,7 +311,7 @@ proc toPackedLib(l: PLib; c: var PackedEncoder; m: var PackedModule): PackedLib result.name = toLitId($l.name, m) storeNode(result, l, path) -proc toPackedSym*(s: PSym; c: var PackedEncoder; m: var PackedModule): PackedItemId = +proc storeSym*(s: PSym; c: var PackedEncoder; m: var PackedModule): PackedItemId = ## serialize a psym if s.isNil: return nilItemId @@ -321,7 +342,7 @@ proc toPackedSym*(s: PSym; c: var PackedEncoder; m: var PackedModule): PackedIte p.externalName = toLitId(if s.loc.r.isNil: "" else: $s.loc.r, m) c.addMissing s.typ - p.typ = s.typ.toPackedType(c, m) + p.typ = s.typ.storeType(c, m) c.addMissing s.owner p.owner = s.owner.safeItemId(c, m) p.annex = toPackedLib(s.annex, c, m) @@ -334,70 +355,77 @@ proc toPackedSym*(s: PSym; c: var PackedEncoder; m: var PackedModule): PackedIte assert s.itemId.module >= 0 result = PackedItemId(module: toLitId(s.itemId.module.FileIndex, c, m), item: s.itemId.item) -proc toSymNode(n: PNode; ir: var PackedTree; c: var PackedEncoder; m: var PackedModule) = - ## store a local or remote psym reference in the tree - assert n.kind == nkSym - template s: PSym = n.sym - let id = s.toPackedSym(c, m).item - if s.itemId.module == c.thisModule: - # it is a symbol that belongs to the module we're currently - # packing: - ir.addSym(id, toPackedInfo(n.info, c, m)) - else: - # store it as an external module reference: - addModuleRef(n, ir, c, m) +proc addModuleRef(n: PNode; ir: var PackedTree; c: var PackedEncoder; m: var PackedModule) = + ## add a remote symbol reference to the tree + let info = n.info.toPackedInfo(c, m) + ir.nodes.add PackedNode(kind: nkModuleRef, operand: 3.int32, # spans 3 nodes in total + typeId: storeTypeLater(n.typ, c, m), info: info) + ir.nodes.add PackedNode(kind: nkInt32Lit, info: info, + operand: toLitId(n.sym.itemId.module.FileIndex, c, m).int32) + ir.nodes.add PackedNode(kind: nkInt32Lit, info: info, + operand: n.sym.itemId.item) proc toPackedNode*(n: PNode; ir: var PackedTree; c: var PackedEncoder; m: var PackedModule) = ## serialize a node into the tree - if n.isNil: return + if n == nil: + ir.nodes.add PackedNode(kind: nkNilRodNode, flags: {}, operand: 1) + return let info = toPackedInfo(n.info, c, m) case n.kind of nkNone, nkEmpty, nkNilLit, nkType: ir.nodes.add PackedNode(kind: n.kind, flags: n.flags, operand: 0, - typeId: toPackedType(n.typ, c, m), info: info) + typeId: storeTypeLater(n.typ, c, m), info: info) of nkIdent: ir.nodes.add PackedNode(kind: n.kind, flags: n.flags, operand: int32 getOrIncl(m.sh.strings, n.ident.s), - typeId: toPackedType(n.typ, c, m), info: info) + typeId: storeTypeLater(n.typ, c, m), info: info) of nkSym: - toSymNode(n, ir, c, m) + if n.sym.itemId.module == c.thisModule: + # it is a symbol that belongs to the module we're currently + # packing: + let id = n.sym.storeSymLater(c, m).item + ir.nodes.add PackedNode(kind: nkSym, flags: n.flags, operand: id, + typeId: storeTypeLater(n.typ, c, m), info: info) + else: + # store it as an external module reference: + addModuleRef(n, ir, c, m) of directIntLit: ir.nodes.add PackedNode(kind: n.kind, flags: n.flags, operand: int32(n.intVal), - typeId: toPackedType(n.typ, c, m), info: info) + typeId: storeTypeLater(n.typ, c, m), info: info) of externIntLit: ir.nodes.add PackedNode(kind: n.kind, flags: n.flags, operand: int32 getOrIncl(m.sh.integers, n.intVal), - typeId: toPackedType(n.typ, c, m), info: info) + typeId: storeTypeLater(n.typ, c, m), info: info) of nkStrLit..nkTripleStrLit: ir.nodes.add PackedNode(kind: n.kind, flags: n.flags, operand: int32 getOrIncl(m.sh.strings, n.strVal), - typeId: toPackedType(n.typ, c, m), info: info) + typeId: storeTypeLater(n.typ, c, m), info: info) of nkFloatLit..nkFloat128Lit: ir.nodes.add PackedNode(kind: n.kind, flags: n.flags, operand: int32 getOrIncl(m.sh.floats, n.floatVal), - typeId: toPackedType(n.typ, c, m), info: info) + typeId: storeTypeLater(n.typ, c, m), info: info) else: let patchPos = ir.prepare(n.kind, n.flags, - toPackedType(n.typ, c, m), info) + storeTypeLater(n.typ, c, m), info) for i in 0..<n.len: toPackedNode(n[i], ir, c, m) ir.patch patchPos - when false: - ir.flush c # flush any pending types and symbols - proc addPragmaComputation*(c: var PackedEncoder; m: var PackedModule; n: PNode) = toPackedNode(n, m.toReplay, c, m) -proc toPackedNodeIgnoreProcDefs*(n: PNode, encoder: var PackedEncoder; m: var PackedModule) = +proc toPackedNodeIgnoreProcDefs(n: PNode, encoder: var PackedEncoder; m: var PackedModule) = case n.kind of routineDefs: # we serialize n[namePos].sym instead if n[namePos].kind == nkSym: - discard toPackedSym(n[namePos].sym, encoder, m) + discard storeSym(n[namePos].sym, encoder, m) else: toPackedNode(n, m.topLevel, encoder, m) + of nkStmtList, nkStmtListExpr: + for it in n: + toPackedNodeIgnoreProcDefs(it, encoder, m) else: toPackedNode(n, m.topLevel, encoder, m) @@ -549,7 +577,7 @@ type type ModuleStatus* = enum undefined, - storing, + storing, # state is strictly for stress-testing purposes loading, loaded, outdated @@ -586,6 +614,10 @@ proc translateLineInfo(c: var PackedDecoder; g: var PackedModuleGraph; thisModul proc loadNodes(c: var PackedDecoder; g: var PackedModuleGraph; thisModule: int; tree: PackedTree; n: NodePos): PNode = let k = n.kind + if k == nkNilRodNode: + return nil + when false: + echo "loading node ", c.config $ translateLineInfo(c, g, thisModule, n.info) result = newNodeIT(k, translateLineInfo(c, g, thisModule, n.info), loadType(c, g, thisModule, n.typ)) result.flags = n.flags @@ -613,7 +645,7 @@ proc loadNodes(c: var PackedDecoder; g: var PackedModuleGraph; thisModule: int; result.sym = loadSym(c, g, thisModule, PackedItemId(module: n1.litId, item: tree.nodes[n2.int].operand)) else: for n0 in sonsReadonly(tree, n): - result.add loadNodes(c, g, thisModule, tree, n0) + result.addAllowNil loadNodes(c, g, thisModule, tree, n0) proc loadProcHeader(c: var PackedDecoder; g: var PackedModuleGraph; thisModule: int; tree: PackedTree; n: NodePos): PNode = @@ -705,13 +737,11 @@ proc loadSym(c: var PackedDecoder; g: var PackedModuleGraph; thisModule: int; s: setLen g[si].syms, g[si].fromDisk.sh.syms.len if g[si].syms[s.item] == nil: - let packed = addr(g[si].fromDisk.sh.syms[s.item]) - - if packed.kind != skModule: - result = symHeaderFromPacked(c, g, packed[], si, s.item) + if g[si].fromDisk.sh.syms[s.item].kind != skModule: + result = symHeaderFromPacked(c, g, g[si].fromDisk.sh.syms[s.item], si, s.item) # store it here early on, so that recursions work properly: g[si].syms[s.item] = result - symBodyFromPacked(c, g, packed[], si, s.item, result) + symBodyFromPacked(c, g, g[si].fromDisk.sh.syms[s.item], si, s.item, result) else: result = g[si].module assert result != nil @@ -724,7 +754,8 @@ proc typeHeaderFromPacked(c: var PackedDecoder; g: var PackedModuleGraph; result = PType(itemId: ItemId(module: si, item: t.nonUniqueId), kind: t.kind, flags: t.flags, size: t.size, align: t.align, paddingAtEnd: t.paddingAtEnd, lockLevel: t.lockLevel, - uniqueId: ItemId(module: si, item: item)) + uniqueId: ItemId(module: si, item: item), + callConv: t.callConv) proc typeBodyFromPacked(c: var PackedDecoder; g: var PackedModuleGraph; t: PackedType; si, item: int32; result: PType) = @@ -745,18 +776,20 @@ proc loadType(c: var PackedDecoder; g: var PackedModuleGraph; thisModule: int; t else: let si = moduleIndex(c, g, thisModule, t) assert g[si].status in {loaded, storing} + assert t.item > 0 + if not g[si].typesInit: g[si].typesInit = true setLen g[si].types, g[si].fromDisk.sh.types.len if g[si].types[t.item] == nil: - let packed = addr(g[si].fromDisk.sh.types[t.item]) - result = typeHeaderFromPacked(c, g, packed[], si, t.item) + result = typeHeaderFromPacked(c, g, g[si].fromDisk.sh.types[t.item], si, t.item) # store it here early on, so that recursions work properly: g[si].types[t.item] = result - typeBodyFromPacked(c, g, packed[], si, t.item, result) + typeBodyFromPacked(c, g, g[si].fromDisk.sh.types[t.item], si, t.item, result) else: result = g[si].types[t.item] + assert result.itemId.item > 0 proc setupLookupTables(g: var PackedModuleGraph; conf: ConfigRef; cache: IdentCache; fileIdx: FileIndex; m: var LoadedModule) = @@ -794,6 +827,7 @@ proc loadToReplayNodes(g: var PackedModuleGraph; conf: ConfigRef; cache: IdentCa proc needsRecompile(g: var PackedModuleGraph; conf: ConfigRef; cache: IdentCache; fileIdx: FileIndex): bool = + # Does the file belong to the fileIdx need to be recompiled? let m = int(fileIdx) if m >= g.len: g.setLen(m+1) @@ -822,6 +856,7 @@ proc needsRecompile(g: var PackedModuleGraph; conf: ConfigRef; cache: IdentCache g[m].status = outdated result = true of loading, loaded: + # For loading: Assume no recompile is required. result = false of outdated, storing: result = true @@ -857,6 +892,19 @@ proc loadProcBody*(config: ConfigRef, cache: IdentCache; assert pos != emptyNodeId result = loadProcBody(decoder, g, mId, g[mId].fromDisk.bodies, NodePos pos) +proc checkForHoles(m: PackedModule; config: ConfigRef; moduleId: int) = + var bugs = 0 + for i in 1 .. high(m.sh.syms): + if m.sh.syms[i].kind == skUnknown: + echo "EMPTY ID ", i, " module ", moduleId, " ", toFullPath(config, FileIndex(moduleId)) + inc bugs + assert bugs == 0 + when false: + var nones = 0 + for i in 1 .. high(m.sh.types): + inc nones, m.sh.types[i].kind == tyNone + assert nones < 1 + proc simulateLoadedModule*(g: var PackedModuleGraph; conf: ConfigRef; cache: IdentCache; moduleSym: PSym; m: PackedModule) = # For now only used for heavy debugging. In the future we could use this to reduce the diff --git a/compiler/magicsys.nim b/compiler/magicsys.nim index e79be6776..74cc07df5 100644 --- a/compiler/magicsys.nim +++ b/compiler/magicsys.nim @@ -17,9 +17,6 @@ export createMagic proc nilOrSysInt*(g: ModuleGraph): PType = g.sysTypes[tyInt] -proc registerSysType*(g: ModuleGraph; t: PType) = - if g.sysTypes[t.kind] == nil: g.sysTypes[t.kind] = t - proc newSysType(g: ModuleGraph; kind: TTypeKind, size: int): PType = result = newType(kind, nextTypeId(g.idgen), g.systemModule) result.size = size @@ -88,24 +85,6 @@ proc resetSysTypes*(g: ModuleGraph) = for i in low(g.sysTypes)..high(g.sysTypes): g.sysTypes[i] = nil - for i in low(g.intTypeCache)..high(g.intTypeCache): - g.intTypeCache[i] = nil - -proc getIntLitType*(g: ModuleGraph; literal: PNode): PType = - # we cache some common integer literal types for performance: - let value = literal.intVal - if value >= low(g.intTypeCache) and value <= high(g.intTypeCache): - result = g.intTypeCache[value.int] - if result == nil: - let ti = getSysType(g, literal.info, tyInt) - result = copyType(ti, nextTypeId(g.idgen), ti.owner) - result.n = literal - g.intTypeCache[value.int] = result - else: - let ti = getSysType(g, literal.info, tyInt) - result = copyType(ti, nextTypeId(g.idgen), ti.owner) - result.n = literal - proc getFloatLitType*(g: ModuleGraph; literal: PNode): PType = # for now we do not cache these: result = newSysType(g, tyFloat, size=8) @@ -125,35 +104,6 @@ proc addSonSkipIntLit*(father, son: PType; id: IdGenerator) = father.sons.add(s) propagateToOwner(father, s) -proc setIntLitType*(g: ModuleGraph; result: PNode) = - let i = result.intVal - case g.config.target.intSize - of 8: result.typ = getIntLitType(g, result) - of 4: - if i >= low(int32) and i <= high(int32): - result.typ = getIntLitType(g, result) - else: - result.typ = getSysType(g, result.info, tyInt64) - of 2: - if i >= low(int16) and i <= high(int16): - result.typ = getIntLitType(g, result) - elif i >= low(int32) and i <= high(int32): - result.typ = getSysType(g, result.info, tyInt32) - else: - result.typ = getSysType(g, result.info, tyInt64) - of 1: - # 8 bit CPUs are insane ... - if i >= low(int8) and i <= high(int8): - result.typ = getIntLitType(g, result) - elif i >= low(int16) and i <= high(int16): - result.typ = getSysType(g, result.info, tyInt16) - elif i >= low(int32) and i <= high(int32): - result.typ = getSysType(g, result.info, tyInt32) - else: - result.typ = getSysType(g, result.info, tyInt64) - else: - internalError(g.config, result.info, "invalid int size") - proc getCompilerProc*(g: ModuleGraph; name: string): PSym = let ident = getIdent(g.cache, name) result = strTableGet(g.compilerprocs, ident) diff --git a/compiler/modulegraphs.nim b/compiler/modulegraphs.nim index 9b174d281..8498cb2b9 100644 --- a/compiler/modulegraphs.nim +++ b/compiler/modulegraphs.nim @@ -55,16 +55,14 @@ type compilerprocs*: TStrTable exposed*: TStrTable packageTypes*: TStrTable - intTypeCache*: array[-5..64, PType] - opContains*, opNot*: PSym emptyNode*: PNode canonTypes*: Table[SigHash, PType] symBodyHashes*: Table[int, SigHash] # symId to digest mapping importModuleCallback*: proc (graph: ModuleGraph; m: PSym, fileIdx: FileIndex): PSym {.nimcall.} includeFileCallback*: proc (graph: ModuleGraph; m: PSym, fileIdx: FileIndex): PNode {.nimcall.} - cacheSeqs*: Table[string, PNode] # state that is shared to support the 'macrocache' API - cacheCounters*: Table[string, BiggestInt] - cacheTables*: Table[string, BTree[string, PNode]] + cacheSeqs*: Table[string, PNode] # state that is shared to support the 'macrocache' API; IC: implemented + cacheCounters*: Table[string, BiggestInt] # IC: implemented + cacheTables*: Table[string, BTree[string, PNode]] # IC: implemented passes*: seq[TPass] onDefinition*: proc (graph: ModuleGraph; s: PSym; info: TLineInfo) {.nimcall.} onDefinitionResolveForward*: proc (graph: ModuleGraph; s: PSym; info: TLineInfo) {.nimcall.} @@ -245,6 +243,8 @@ proc registerModule*(g: ModuleGraph; m: PSym) = proc newModuleGraph*(cache: IdentCache; config: ConfigRef): ModuleGraph = result = ModuleGraph() + # A module ID of -1 means that the symbol is not attached to a module at all, + # but to the module graph: result.idgen = IdGenerator(module: -1'i32, symId: 0'i32, typeId: 0'i32) initStrTable(result.packageSyms) result.deps = initIntSet() @@ -259,8 +259,6 @@ proc newModuleGraph*(cache: IdentCache; config: ConfigRef): ModuleGraph = initStrTable(result.compilerprocs) initStrTable(result.exposed) initStrTable(result.packageTypes) - result.opNot = createMagic(result, "not", mNot) - result.opContains = createMagic(result, "contains", mInSet) result.emptyNode = newNode(nkEmpty) result.cacheSeqs = initTable[string, PNode]() result.cacheCounters = initTable[string, BiggestInt]() diff --git a/compiler/sem.nim b/compiler/sem.nim index 6f3b15867..15b7eee4a 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -505,6 +505,8 @@ proc addCodeForGenerics(c: PContext, n: PNode) = proc myOpen(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext {.nosinks.} = var c = newContext(graph, module) c.idgen = idgen + c.enforceVoidContext = newType(tyTyped, nextTypeId(idgen), nil) + if c.p != nil: internalError(graph.config, module.info, "sem.myOpen") c.semConstExpr = semConstExpr c.semExpr = semExpr diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 583077fbf..d974f6048 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -93,6 +93,9 @@ type imports*: seq[ImportedModule] # scope for all imported symbols topLevelScope*: PScope # scope for all top-level symbols p*: PProcCon # procedure context + intTypeCache*: array[-5..32, PType] # cache some common integer types + # to avoid type allocations + nilTypeCache*: PType matchedConcept*: ptr TMatchedConcept # the current concept being matched friendModules*: seq[PSym] # friend modules; may access private data; # this is used so that generic instantiations @@ -149,17 +152,56 @@ type isAmbiguous*: bool # little hack features*: set[Feature] inTypeContext*: int - typesWithOps*: seq[(PType, PType)] #\ - # We need to instantiate the type bound ops lazily after - # the generic type has been constructed completely. See - # tests/destructor/topttree.nim for an example that - # would otherwise fail. unusedImports*: seq[(PSym, TLineInfo)] exportIndirections*: HashSet[(int, int)] lastTLineInfo*: TLineInfo template config*(c: PContext): ConfigRef = c.graph.config +proc getIntLitType*(c: PContext; literal: PNode): PType = + # we cache some common integer literal types for performance: + let value = literal.intVal + if value >= low(c.intTypeCache) and value <= high(c.intTypeCache): + result = c.intTypeCache[value.int] + if result == nil: + let ti = getSysType(c.graph, literal.info, tyInt) + result = copyType(ti, nextTypeId(c.idgen), ti.owner) + result.n = literal + c.intTypeCache[value.int] = result + else: + let ti = getSysType(c.graph, literal.info, tyInt) + result = copyType(ti, nextTypeId(c.idgen), ti.owner) + result.n = literal + +proc setIntLitType*(c: PContext; result: PNode) = + let i = result.intVal + case c.config.target.intSize + of 8: result.typ = getIntLitType(c, result) + of 4: + if i >= low(int32) and i <= high(int32): + result.typ = getIntLitType(c, result) + else: + result.typ = getSysType(c.graph, result.info, tyInt64) + of 2: + if i >= low(int16) and i <= high(int16): + result.typ = getIntLitType(c, result) + elif i >= low(int32) and i <= high(int32): + result.typ = getSysType(c.graph, result.info, tyInt32) + else: + result.typ = getSysType(c.graph, result.info, tyInt64) + of 1: + # 8 bit CPUs are insane ... + if i >= low(int8) and i <= high(int8): + result.typ = getIntLitType(c, result) + elif i >= low(int16) and i <= high(int16): + result.typ = getSysType(c.graph, result.info, tyInt16) + elif i >= low(int32) and i <= high(int32): + result.typ = getSysType(c.graph, result.info, tyInt32) + else: + result.typ = getSysType(c.graph, result.info, tyInt64) + else: + internalError(c.config, result.info, "invalid int size") + proc makeInstPair*(s: PSym, inst: PInstantiation): TInstantiationPair = result.genericSym = s result.inst = inst @@ -250,7 +292,6 @@ proc popOptionEntry*(c: PContext) = proc newContext*(graph: ModuleGraph; module: PSym): PContext = new(result) - result.enforceVoidContext = PType(kind: tyTyped) result.optionStack = @[newOptionEntry(graph.config)] result.libs = @[] result.module = module @@ -265,7 +306,6 @@ proc newContext*(graph: ModuleGraph; module: PSym): PContext = result.cache = graph.cache result.graph = graph initStrTable(result.signatures) - result.typesWithOps = @[] result.features = graph.config.features if graph.config.symbolFiles != disabledSf: let id = module.position diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 4a04cfb6d..343ff0eda 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1072,7 +1072,7 @@ proc lookupInRecordAndBuildCheck(c: PContext, n, r: PNode, field: PIdent, s = newNodeIT(nkCurly, n.info, setType) for j in 0..<it.len - 1: s.add copyTree(it[j]) var inExpr = newNodeIT(nkCall, n.info, getSysType(c.graph, n.info, tyBool)) - inExpr.add newSymNode(c.graph.opContains, n.info) + inExpr.add newSymNode(getSysMagic(c.graph, n.info, "contains", mInSet), n.info) inExpr.add s inExpr.add copyTree(r[0]) check.add inExpr @@ -1085,11 +1085,11 @@ proc lookupInRecordAndBuildCheck(c: PContext, n, r: PNode, field: PIdent, check = newNodeI(nkCheckedFieldExpr, n.info) check.add c.graph.emptyNode # make space for access node var inExpr = newNodeIT(nkCall, n.info, getSysType(c.graph, n.info, tyBool)) - inExpr.add newSymNode(c.graph.opContains, n.info) + inExpr.add newSymNode(getSysMagic(c.graph, n.info, "contains", mInSet), n.info) inExpr.add s inExpr.add copyTree(r[0]) var notExpr = newNodeIT(nkCall, n.info, getSysType(c.graph, n.info, tyBool)) - notExpr.add newSymNode(c.graph.opNot, n.info) + notExpr.add newSymNode(getSysMagic(c.graph, n.info, "not", mNot), n.info) notExpr.add inExpr check.add notExpr return @@ -2641,6 +2641,14 @@ proc hoistParamsUsedInDefault(c: PContext, call, letSection, defExpr: var PNode) for i in 0..<defExpr.safeLen: hoistParamsUsedInDefault(c, call, letSection, defExpr[i]) +proc getNilType(c: PContext): PType = + result = c.nilTypeCache + if result == nil: + result = newTypeS(tyNil, c) + result.size = c.config.target.ptrSize + result.align = c.config.target.ptrSize.int16 + c.nilTypeCache = result + proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = when defined(nimCompilerStackraceHints): setFrameMsg c.config$n.info & " " & $n.kind @@ -2676,9 +2684,9 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = of nkEmpty, nkNone, nkCommentStmt, nkType: discard of nkNilLit: - if result.typ == nil: result.typ = getSysType(c.graph, n.info, tyNil) + if result.typ == nil: result.typ = getNilType(c) of nkIntLit: - if result.typ == nil: setIntLitType(c.graph, result) + if result.typ == nil: setIntLitType(c, result) of nkInt8Lit: if result.typ == nil: result.typ = getSysType(c.graph, n.info, tyInt8) of nkInt16Lit: diff --git a/compiler/semfold.nim b/compiler/semfold.nim index 4cc2dcba0..a3b9a8dde 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -22,13 +22,19 @@ proc errorType*(g: ModuleGraph): PType = result = newType(tyError, nextTypeId(g.idgen), g.owners[^1]) result.flags.incl tfCheckedForDestructor -proc newIntNodeT*(intVal: Int128, n: PNode; g: ModuleGraph): PNode = +proc getIntLitTypeG(g: ModuleGraph; literal: PNode; idgen: IdGenerator): PType = + # we cache some common integer literal types for performance: + let ti = getSysType(g, literal.info, tyInt) + result = copyType(ti, nextTypeId(idgen), ti.owner) + result.n = literal + +proc newIntNodeT*(intVal: Int128, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode = result = newIntTypeNode(intVal, n.typ) # See bug #6989. 'pred' et al only produce an int literal type if the # original type was 'int', not a distinct int etc. if n.typ.kind == tyInt: # access cache for the int lit type - result.typ = getIntLitType(g, result) + result.typ = getIntLitTypeG(g, result, idgen) result.info = n.info proc newFloatNodeT*(floatVal: BiggestFloat, n: PNode; g: ModuleGraph): PNode = @@ -47,33 +53,33 @@ proc newStrNodeT*(strVal: string, n: PNode; g: ModuleGraph): PNode = proc getConstExpr*(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode # evaluates the constant expression or returns nil if it is no constant # expression -proc evalOp*(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode +proc evalOp*(m: TMagic, n, a, b, c: PNode; idgen: IdGenerator; g: ModuleGraph): PNode proc checkInRange(conf: ConfigRef; n: PNode, res: Int128): bool = res in firstOrd(conf, n.typ)..lastOrd(conf, n.typ) -proc foldAdd(a, b: Int128, n: PNode; g: ModuleGraph): PNode = +proc foldAdd(a, b: Int128, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode = let res = a + b if checkInRange(g.config, n, res): - result = newIntNodeT(res, n, g) + result = newIntNodeT(res, n, idgen, g) -proc foldSub(a, b: Int128, n: PNode; g: ModuleGraph): PNode = +proc foldSub(a, b: Int128, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode = let res = a - b if checkInRange(g.config, n, res): - result = newIntNodeT(res, n, g) + result = newIntNodeT(res, n, idgen, g) -proc foldUnarySub(a: Int128, n: PNode, g: ModuleGraph): PNode = +proc foldUnarySub(a: Int128, n: PNode; idgen: IdGenerator, g: ModuleGraph): PNode = if a != firstOrd(g.config, n.typ): - result = newIntNodeT(-a, n, g) + result = newIntNodeT(-a, n, idgen, g) -proc foldAbs(a: Int128, n: PNode; g: ModuleGraph): PNode = +proc foldAbs(a: Int128, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode = if a != firstOrd(g.config, n.typ): - result = newIntNodeT(abs(a), n, g) + result = newIntNodeT(abs(a), n, idgen, g) -proc foldMul(a, b: Int128, n: PNode; g: ModuleGraph): PNode = +proc foldMul(a, b: Int128, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode = let res = a * b if checkInRange(g.config, n, res): - return newIntNodeT(res, n, g) + return newIntNodeT(res, n, idgen, g) proc ordinalValToString*(a: PNode; g: ModuleGraph): string = # because $ has the param ordinal[T], `a` is not necessarily an enum, but an @@ -115,68 +121,68 @@ proc pickIntRange(a, b: PType): PType = proc isIntRangeOrLit(t: PType): bool = result = isIntRange(t) or isIntLit(t) -proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode = +proc evalOp(m: TMagic, n, a, b, c: PNode; idgen: IdGenerator; g: ModuleGraph): PNode = # b and c may be nil result = nil case m - of mOrd: result = newIntNodeT(getOrdValue(a), n, g) - of mChr: result = newIntNodeT(getInt(a), n, g) - of mUnaryMinusI, mUnaryMinusI64: result = foldUnarySub(getInt(a), n, g) + of mOrd: result = newIntNodeT(getOrdValue(a), n, idgen, g) + of mChr: result = newIntNodeT(getInt(a), n, idgen, g) + of mUnaryMinusI, mUnaryMinusI64: result = foldUnarySub(getInt(a), n, idgen, g) of mUnaryMinusF64: result = newFloatNodeT(-getFloat(a), n, g) - of mNot: result = newIntNodeT(One - getInt(a), n, g) - of mCard: result = newIntNodeT(toInt128(nimsets.cardSet(g.config, a)), n, g) + of mNot: result = newIntNodeT(One - getInt(a), n, idgen, g) + of mCard: result = newIntNodeT(toInt128(nimsets.cardSet(g.config, a)), n, idgen, g) of mBitnotI: if n.typ.isUnsigned: - result = newIntNodeT(bitnot(getInt(a)).maskBytes(int(n.typ.size)), n, g) + result = newIntNodeT(bitnot(getInt(a)).maskBytes(int(n.typ.size)), n, idgen, g) else: - result = newIntNodeT(bitnot(getInt(a)), n, g) - of mLengthArray: result = newIntNodeT(lengthOrd(g.config, a.typ), n, g) + result = newIntNodeT(bitnot(getInt(a)), n, idgen, g) + of mLengthArray: result = newIntNodeT(lengthOrd(g.config, a.typ), n, idgen, g) of mLengthSeq, mLengthOpenArray, mLengthStr: if a.kind == nkNilLit: - result = newIntNodeT(Zero, n, g) + result = newIntNodeT(Zero, n, idgen, g) elif a.kind in {nkStrLit..nkTripleStrLit}: if a.typ.kind == tyString: - result = newIntNodeT(toInt128(a.strVal.len), n, g) + result = newIntNodeT(toInt128(a.strVal.len), n, idgen, g) elif a.typ.kind == tyCString: - result = newIntNodeT(toInt128(nimCStrLen(a.strVal)), n, g) + result = newIntNodeT(toInt128(nimCStrLen(a.strVal)), n, idgen, g) else: - result = newIntNodeT(toInt128(a.len), n, g) + result = newIntNodeT(toInt128(a.len), n, idgen, g) of mUnaryPlusI, mUnaryPlusF64: result = a # throw `+` away # XXX: Hides overflow/underflow - of mAbsI: result = foldAbs(getInt(a), n, g) - of mSucc: result = foldAdd(getOrdValue(a), getInt(b), n, g) - of mPred: result = foldSub(getOrdValue(a), getInt(b), n, g) - of mAddI: result = foldAdd(getInt(a), getInt(b), n, g) - of mSubI: result = foldSub(getInt(a), getInt(b), n, g) - of mMulI: result = foldMul(getInt(a), getInt(b), n, g) + of mAbsI: result = foldAbs(getInt(a), n, idgen, g) + of mSucc: result = foldAdd(getOrdValue(a), getInt(b), n, idgen, g) + of mPred: result = foldSub(getOrdValue(a), getInt(b), n, idgen, g) + of mAddI: result = foldAdd(getInt(a), getInt(b), n, idgen, g) + of mSubI: result = foldSub(getInt(a), getInt(b), n, idgen, g) + of mMulI: result = foldMul(getInt(a), getInt(b), n, idgen, g) of mMinI: let argA = getInt(a) let argB = getInt(b) - result = newIntNodeT(if argA < argB: argA else: argB, n, g) + result = newIntNodeT(if argA < argB: argA else: argB, n, idgen, g) of mMaxI: let argA = getInt(a) let argB = getInt(b) - result = newIntNodeT(if argA > argB: argA else: argB, n, g) + result = newIntNodeT(if argA > argB: argA else: argB, n, idgen, g) of mShlI: case skipTypes(n.typ, abstractRange).kind - of tyInt8: result = newIntNodeT(toInt128(toInt8(getInt(a)) shl toInt64(getInt(b))), n, g) - of tyInt16: result = newIntNodeT(toInt128(toInt16(getInt(a)) shl toInt64(getInt(b))), n, g) - of tyInt32: result = newIntNodeT(toInt128(toInt32(getInt(a)) shl toInt64(getInt(b))), n, g) - of tyInt64: result = newIntNodeT(toInt128(toInt64(getInt(a)) shl toInt64(getInt(b))), n, g) + of tyInt8: result = newIntNodeT(toInt128(toInt8(getInt(a)) shl toInt64(getInt(b))), n, idgen, g) + of tyInt16: result = newIntNodeT(toInt128(toInt16(getInt(a)) shl toInt64(getInt(b))), n, idgen, g) + of tyInt32: result = newIntNodeT(toInt128(toInt32(getInt(a)) shl toInt64(getInt(b))), n, idgen, g) + of tyInt64: result = newIntNodeT(toInt128(toInt64(getInt(a)) shl toInt64(getInt(b))), n, idgen, g) of tyInt: if g.config.target.intSize == 4: - result = newIntNodeT(toInt128(toInt32(getInt(a)) shl toInt64(getInt(b))), n, g) + result = newIntNodeT(toInt128(toInt32(getInt(a)) shl toInt64(getInt(b))), n, idgen, g) else: - result = newIntNodeT(toInt128(toInt64(getInt(a)) shl toInt64(getInt(b))), n, g) - of tyUInt8: result = newIntNodeT(toInt128(toUInt8(getInt(a)) shl toInt64(getInt(b))), n, g) - of tyUInt16: result = newIntNodeT(toInt128(toUInt16(getInt(a)) shl toInt64(getInt(b))), n, g) - of tyUInt32: result = newIntNodeT(toInt128(toUInt32(getInt(a)) shl toInt64(getInt(b))), n, g) - of tyUInt64: result = newIntNodeT(toInt128(toUInt64(getInt(a)) shl toInt64(getInt(b))), n, g) + result = newIntNodeT(toInt128(toInt64(getInt(a)) shl toInt64(getInt(b))), n, idgen, g) + of tyUInt8: result = newIntNodeT(toInt128(toUInt8(getInt(a)) shl toInt64(getInt(b))), n, idgen, g) + of tyUInt16: result = newIntNodeT(toInt128(toUInt16(getInt(a)) shl toInt64(getInt(b))), n, idgen, g) + of tyUInt32: result = newIntNodeT(toInt128(toUInt32(getInt(a)) shl toInt64(getInt(b))), n, idgen, g) + of tyUInt64: result = newIntNodeT(toInt128(toUInt64(getInt(a)) shl toInt64(getInt(b))), n, idgen, g) of tyUInt: if g.config.target.intSize == 4: - result = newIntNodeT(toInt128(toUInt32(getInt(a)) shl toInt64(getInt(b))), n, g) + result = newIntNodeT(toInt128(toUInt32(getInt(a)) shl toInt64(getInt(b))), n, idgen, g) else: - result = newIntNodeT(toInt128(toUInt64(getInt(a)) shl toInt64(getInt(b))), n, g) + result = newIntNodeT(toInt128(toUInt64(getInt(a)) shl toInt64(getInt(b))), n, idgen, g) else: internalError(g.config, n.info, "constant folding for shl") of mShrI: var a = cast[uint64](getInt(a)) @@ -197,75 +203,75 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode = # unsigned and 64 bit integers don't need masking discard let c = cast[BiggestInt](a shr b) - result = newIntNodeT(toInt128(c), n, g) + result = newIntNodeT(toInt128(c), n, idgen, g) of mAshrI: case skipTypes(n.typ, abstractRange).kind - of tyInt8: result = newIntNodeT(toInt128(ashr(toInt8(getInt(a)), toInt8(getInt(b)))), n, g) - of tyInt16: result = newIntNodeT(toInt128(ashr(toInt16(getInt(a)), toInt16(getInt(b)))), n, g) - of tyInt32: result = newIntNodeT(toInt128(ashr(toInt32(getInt(a)), toInt32(getInt(b)))), n, g) + of tyInt8: result = newIntNodeT(toInt128(ashr(toInt8(getInt(a)), toInt8(getInt(b)))), n, idgen, g) + of tyInt16: result = newIntNodeT(toInt128(ashr(toInt16(getInt(a)), toInt16(getInt(b)))), n, idgen, g) + of tyInt32: result = newIntNodeT(toInt128(ashr(toInt32(getInt(a)), toInt32(getInt(b)))), n, idgen, g) of tyInt64, tyInt: - result = newIntNodeT(toInt128(ashr(toInt64(getInt(a)), toInt64(getInt(b)))), n, g) + result = newIntNodeT(toInt128(ashr(toInt64(getInt(a)), toInt64(getInt(b)))), n, idgen, g) else: internalError(g.config, n.info, "constant folding for ashr") of mDivI: let argA = getInt(a) let argB = getInt(b) if argB != Zero and (argA != firstOrd(g.config, n.typ) or argB != NegOne): - result = newIntNodeT(argA div argB, n, g) + result = newIntNodeT(argA div argB, n, idgen, g) of mModI: let argA = getInt(a) let argB = getInt(b) if argB != Zero and (argA != firstOrd(g.config, n.typ) or argB != NegOne): - result = newIntNodeT(argA mod argB, n, g) + result = newIntNodeT(argA mod argB, n, idgen, g) of mAddF64: result = newFloatNodeT(getFloat(a) + getFloat(b), n, g) of mSubF64: result = newFloatNodeT(getFloat(a) - getFloat(b), n, g) of mMulF64: result = newFloatNodeT(getFloat(a) * getFloat(b), n, g) of mDivF64: result = newFloatNodeT(getFloat(a) / getFloat(b), n, g) - of mIsNil: result = newIntNodeT(toInt128(ord(a.kind == nkNilLit)), n, g) + of mIsNil: result = newIntNodeT(toInt128(ord(a.kind == nkNilLit)), n, idgen, g) of mLtI, mLtB, mLtEnum, mLtCh: - result = newIntNodeT(toInt128(ord(getOrdValue(a) < getOrdValue(b))), n, g) + result = newIntNodeT(toInt128(ord(getOrdValue(a) < getOrdValue(b))), n, idgen, g) of mLeI, mLeB, mLeEnum, mLeCh: - result = newIntNodeT(toInt128(ord(getOrdValue(a) <= getOrdValue(b))), n, g) + result = newIntNodeT(toInt128(ord(getOrdValue(a) <= getOrdValue(b))), n, idgen, g) of mEqI, mEqB, mEqEnum, mEqCh: - result = newIntNodeT(toInt128(ord(getOrdValue(a) == getOrdValue(b))), n, g) - of mLtF64: result = newIntNodeT(toInt128(ord(getFloat(a) < getFloat(b))), n, g) - of mLeF64: result = newIntNodeT(toInt128(ord(getFloat(a) <= getFloat(b))), n, g) - of mEqF64: result = newIntNodeT(toInt128(ord(getFloat(a) == getFloat(b))), n, g) - of mLtStr: result = newIntNodeT(toInt128(ord(getStr(a) < getStr(b))), n, g) - of mLeStr: result = newIntNodeT(toInt128(ord(getStr(a) <= getStr(b))), n, g) - of mEqStr: result = newIntNodeT(toInt128(ord(getStr(a) == getStr(b))), n, g) + result = newIntNodeT(toInt128(ord(getOrdValue(a) == getOrdValue(b))), n, idgen, g) + of mLtF64: result = newIntNodeT(toInt128(ord(getFloat(a) < getFloat(b))), n, idgen, g) + of mLeF64: result = newIntNodeT(toInt128(ord(getFloat(a) <= getFloat(b))), n, idgen, g) + of mEqF64: result = newIntNodeT(toInt128(ord(getFloat(a) == getFloat(b))), n, idgen, g) + of mLtStr: result = newIntNodeT(toInt128(ord(getStr(a) < getStr(b))), n, idgen, g) + of mLeStr: result = newIntNodeT(toInt128(ord(getStr(a) <= getStr(b))), n, idgen, g) + of mEqStr: result = newIntNodeT(toInt128(ord(getStr(a) == getStr(b))), n, idgen, g) of mLtU: - result = newIntNodeT(toInt128(ord(`<%`(toInt64(getOrdValue(a)), toInt64(getOrdValue(b))))), n, g) + result = newIntNodeT(toInt128(ord(`<%`(toInt64(getOrdValue(a)), toInt64(getOrdValue(b))))), n, idgen, g) of mLeU: - result = newIntNodeT(toInt128(ord(`<=%`(toInt64(getOrdValue(a)), toInt64(getOrdValue(b))))), n, g) - of mBitandI, mAnd: result = newIntNodeT(bitand(a.getInt, b.getInt), n, g) - of mBitorI, mOr: result = newIntNodeT(bitor(getInt(a), getInt(b)), n, g) - of mBitxorI, mXor: result = newIntNodeT(bitxor(getInt(a), getInt(b)), n, g) + result = newIntNodeT(toInt128(ord(`<=%`(toInt64(getOrdValue(a)), toInt64(getOrdValue(b))))), n, idgen, g) + of mBitandI, mAnd: result = newIntNodeT(bitand(a.getInt, b.getInt), n, idgen, g) + of mBitorI, mOr: result = newIntNodeT(bitor(getInt(a), getInt(b)), n, idgen, g) + of mBitxorI, mXor: result = newIntNodeT(bitxor(getInt(a), getInt(b)), n, idgen, g) of mAddU: let val = maskBytes(getInt(a) + getInt(b), int(n.typ.size)) - result = newIntNodeT(val, n, g) + result = newIntNodeT(val, n, idgen, g) of mSubU: let val = maskBytes(getInt(a) - getInt(b), int(n.typ.size)) - result = newIntNodeT(val, n, g) + result = newIntNodeT(val, n, idgen, g) # echo "subU: ", val, " n: ", n, " result: ", val of mMulU: let val = maskBytes(getInt(a) * getInt(b), int(n.typ.size)) - result = newIntNodeT(val, n, g) + result = newIntNodeT(val, n, idgen, g) of mModU: let argA = maskBytes(getInt(a), int(a.typ.size)) let argB = maskBytes(getInt(b), int(a.typ.size)) if argB != Zero: - result = newIntNodeT(argA mod argB, n, g) + result = newIntNodeT(argA mod argB, n, idgen, g) of mDivU: let argA = maskBytes(getInt(a), int(a.typ.size)) let argB = maskBytes(getInt(b), int(a.typ.size)) if argB != Zero: - result = newIntNodeT(argA div argB, n, g) - of mLeSet: result = newIntNodeT(toInt128(ord(containsSets(g.config, a, b))), n, g) - of mEqSet: result = newIntNodeT(toInt128(ord(equalSets(g.config, a, b))), n, g) + result = newIntNodeT(argA div argB, n, idgen, g) + of mLeSet: result = newIntNodeT(toInt128(ord(containsSets(g.config, a, b))), n, idgen, g) + of mEqSet: result = newIntNodeT(toInt128(ord(equalSets(g.config, a, b))), n, idgen, g) of mLtSet: result = newIntNodeT(toInt128(ord( - containsSets(g.config, a, b) and not equalSets(g.config, a, b))), n, g) + containsSets(g.config, a, b) and not equalSets(g.config, a, b))), n, idgen, g) of mMulSet: result = nimsets.intersectSets(g.config, a, b) result.info = n.info @@ -276,7 +282,7 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode = result = nimsets.diffSets(g.config, a, b) result.info = n.info of mConStrStr: result = newStrNodeT(getStrOrChar(a) & getStrOrChar(b), n, g) - of mInSet: result = newIntNodeT(toInt128(ord(inSet(a, b))), n, g) + of mInSet: result = newIntNodeT(toInt128(ord(inSet(a, b))), n, idgen, g) of mRepr: # BUGFIX: we cannot eval mRepr here for reasons that I forgot. discard @@ -299,13 +305,13 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode = result = copyTree(a) result.typ = n.typ of mCompileOption: - result = newIntNodeT(toInt128(ord(commands.testCompileOption(g.config, a.getStr, n.info))), n, g) + result = newIntNodeT(toInt128(ord(commands.testCompileOption(g.config, a.getStr, n.info))), n, idgen, g) of mCompileOptionArg: result = newIntNodeT(toInt128(ord( - testCompileOptionArg(g.config, getStr(a), getStr(b), n.info))), n, g) + testCompileOptionArg(g.config, getStr(a), getStr(b), n.info))), n, idgen, g) of mEqProc: result = newIntNodeT(toInt128(ord( - exprStructuralEquivalent(a, b, strictSymEquality=true))), n, g) + exprStructuralEquivalent(a, b, strictSymEquality=true))), n, idgen, g) else: discard proc getConstIfExpr(c: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode = @@ -351,7 +357,7 @@ proc magicCall(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode = if n.len > 3: c = getConstExpr(m, n[3], idgen, g) if c == nil: return - result = evalOp(s.magic, n, a, b, c, g) + result = evalOp(s.magic, n, a, b, c, idgen, g) proc getAppType(n: PNode; g: ModuleGraph): PNode = if g.config.globalOptions.contains(optGenDynLib): @@ -368,7 +374,7 @@ proc rangeCheck(n: PNode, value: Int128; g: ModuleGraph) = localError(g.config, n.info, "cannot convert " & $value & " to " & typeToString(n.typ)) -proc foldConv(n, a: PNode; g: ModuleGraph; check = false): PNode = +proc foldConv(n, a: PNode; idgen: IdGenerator; g: ModuleGraph; check = false): PNode = let dstTyp = skipTypes(n.typ, abstractRange - {tyTypeDesc}) let srcTyp = skipTypes(a.typ, abstractRange - {tyTypeDesc}) @@ -382,9 +388,9 @@ proc foldConv(n, a: PNode; g: ModuleGraph; check = false): PNode = of tyBool: case srcTyp.kind of tyFloat..tyFloat64: - result = newIntNodeT(toInt128(getFloat(a) != 0.0), n, g) + result = newIntNodeT(toInt128(getFloat(a) != 0.0), n, idgen, g) of tyChar, tyUInt..tyUInt64, tyInt..tyInt64: - result = newIntNodeT(toInt128(a.getOrdValue != 0), n, g) + result = newIntNodeT(toInt128(a.getOrdValue != 0), n, idgen, g) of tyBool, tyEnum: # xxx shouldn't we disallow `tyEnum`? result = a result.typ = n.typ @@ -392,11 +398,11 @@ proc foldConv(n, a: PNode; g: ModuleGraph; check = false): PNode = of tyInt..tyInt64, tyUInt..tyUInt64: case srcTyp.kind of tyFloat..tyFloat64: - result = newIntNodeT(toInt128(getFloat(a)), n, g) + result = newIntNodeT(toInt128(getFloat(a)), n, idgen, g) of tyChar, tyUInt..tyUInt64, tyInt..tyInt64: var val = a.getOrdValue if check: rangeCheck(n, val, g) - result = newIntNodeT(val, n, g) + result = newIntNodeT(val, n, idgen, g) if dstTyp.kind in {tyUInt..tyUInt64}: result.transitionIntKind(nkUIntLit) else: @@ -493,13 +499,13 @@ proc getConstExpr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode var s = n.sym case s.kind of skEnumField: - result = newIntNodeT(toInt128(s.position), n, g) + result = newIntNodeT(toInt128(s.position), n, idgen, g) of skConst: case s.magic - of mIsMainModule: result = newIntNodeT(toInt128(ord(sfMainModule in m.flags)), n, g) + of mIsMainModule: result = newIntNodeT(toInt128(ord(sfMainModule in m.flags)), n, idgen, g) of mCompileDate: result = newStrNodeT(getDateStr(), n, g) of mCompileTime: result = newStrNodeT(getClockStr(), n, g) - of mCpuEndian: result = newIntNodeT(toInt128(ord(CPU[g.config.target.targetCPU].endian)), n, g) + of mCpuEndian: result = newIntNodeT(toInt128(ord(CPU[g.config.target.targetCPU].endian)), n, idgen, g) of mHostOS: result = newStrNodeT(toLowerAscii(platform.OS[g.config.target.targetOS].name), n, g) of mHostCPU: result = newStrNodeT(platform.CPU[g.config.target.targetCPU].name.toLowerAscii, n, g) of mBuildOS: result = newStrNodeT(toLowerAscii(platform.OS[g.config.target.hostOS].name), n, g) @@ -508,7 +514,7 @@ proc getConstExpr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode of mIntDefine: if isDefined(g.config, s.name.s): try: - result = newIntNodeT(toInt128(g.config.symbols[s.name.s].parseInt), n, g) + result = newIntNodeT(toInt128(g.config.symbols[s.name.s].parseInt), n, idgen, g) except ValueError: localError(g.config, s.info, "{.intdefine.} const was set to an invalid integer: '" & @@ -523,7 +529,7 @@ proc getConstExpr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode of mBoolDefine: if isDefined(g.config, s.name.s): try: - result = newIntNodeT(toInt128(g.config.symbols[s.name.s].parseBool.int), n, g) + result = newIntNodeT(toInt128(g.config.symbols[s.name.s].parseBool.int), n, idgen, g) except ValueError: localError(g.config, s.info, "{.booldefine.} const was set to an invalid bool: '" & @@ -569,30 +575,30 @@ proc getConstExpr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode if skipTypes(n[1].typ, abstractVarRange).kind in tyFloat..tyFloat64: result = newFloatNodeT(firstFloat(n[1].typ), n, g) else: - result = newIntNodeT(firstOrd(g.config, n[1].typ), n, g) + result = newIntNodeT(firstOrd(g.config, n[1].typ), n, idgen, g) of mHigh: if skipTypes(n[1].typ, abstractVar+{tyUserTypeClassInst}).kind notin {tySequence, tyString, tyCString, tyOpenArray, tyVarargs}: if skipTypes(n[1].typ, abstractVarRange).kind in tyFloat..tyFloat64: result = newFloatNodeT(lastFloat(n[1].typ), n, g) else: - result = newIntNodeT(lastOrd(g.config, skipTypes(n[1].typ, abstractVar)), n, g) + result = newIntNodeT(lastOrd(g.config, skipTypes(n[1].typ, abstractVar)), n, idgen, g) else: var a = getArrayConstr(m, n[1], idgen, g) if a.kind == nkBracket: # we can optimize it away: - result = newIntNodeT(toInt128(a.len-1), n, g) + result = newIntNodeT(toInt128(a.len-1), n, idgen, g) of mLengthOpenArray: var a = getArrayConstr(m, n[1], idgen, g) if a.kind == nkBracket: # we can optimize it away! This fixes the bug ``len(134)``. - result = newIntNodeT(toInt128(a.len), n, g) + result = newIntNodeT(toInt128(a.len), n, idgen, g) else: result = magicCall(m, n, idgen, g) of mLengthArray: # It doesn't matter if the argument is const or not for mLengthArray. # This fixes bug #544. - result = newIntNodeT(lengthOrd(g.config, n[1].typ), n, g) + result = newIntNodeT(lengthOrd(g.config, n[1].typ), n, idgen, g) of mSizeOf: result = foldSizeOf(g.config, n, nil) of mAlignOf: @@ -675,7 +681,7 @@ proc getConstExpr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode of nkHiddenStdConv, nkHiddenSubConv, nkConv: var a = getConstExpr(m, n[1], idgen, g) if a == nil: return - result = foldConv(n, a, g, check=true) + result = foldConv(n, a, idgen, g, check=true) of nkDerefExpr, nkHiddenDeref: let a = getConstExpr(m, n[0], idgen, g) if a != nil and a.kind == nkNilLit: diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index 69e414fa8..d5ce04389 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -71,7 +71,7 @@ proc semAsgnOpr(c: PContext; n: PNode): PNode = proc semIsPartOf(c: PContext, n: PNode, flags: TExprFlags): PNode = var r = isPartOf(n[1], n[2]) - result = newIntNodeT(toInt128(ord(r)), n, c.graph) + result = newIntNodeT(toInt128(ord(r)), n, c.idgen, c.graph) proc expectIntLit(c: PContext, n: PNode): int = let x = c.semConstExpr(c, n) @@ -179,15 +179,15 @@ proc evalTypeTrait(c: PContext; traitCall: PNode, operand: PType, context: PSym) let t = operand.skipTypes({tyVar, tyLent, tyGenericInst, tyAlias, tySink, tyInferred}) let complexObj = containsGarbageCollectedRef(t) or hasDestructor(t) - result = newIntNodeT(toInt128(ord(not complexObj)), traitCall, c.graph) + result = newIntNodeT(toInt128(ord(not complexObj)), traitCall, c.idgen, c.graph) of "isNamedTuple": var operand = operand.skipTypes({tyGenericInst}) let cond = operand.kind == tyTuple and operand.n != nil - result = newIntNodeT(toInt128(ord(cond)), traitCall, c.graph) + result = newIntNodeT(toInt128(ord(cond)), traitCall, c.idgen, c.graph) of "tupleLen": var operand = operand.skipTypes({tyGenericInst}) assert operand.kind == tyTuple, $operand.kind - result = newIntNodeT(toInt128(operand.len), traitCall, c.graph) + result = newIntNodeT(toInt128(operand.len), traitCall, c.idgen, c.graph) of "distinctBase": var arg = operand.skipTypes({tyGenericInst}) if arg.kind == tyDistinct: diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index a76116b1c..15fe578f5 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -537,8 +537,6 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = typFlags.incl taConcept typeAllowedCheck(c, a.info, typ, symkind, typFlags) - when false: liftTypeBoundOps(c, typ, a.info) - instAllTypeBoundOp(c, a.info) var tup = skipTypes(typ, {tyGenericInst, tyAlias, tySink}) if a.kind == nkVarTuple: if tup.kind != tyTuple: diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 45f20da9b..057fb7d4a 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -1967,10 +1967,6 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = result = newOrPrevType(tyError, prev, c) n.typ = result dec c.inTypeContext - if false: # c.inTypeContext == 0: - #if $n == "var seq[StackTraceEntry]": - # echo "begin ", n - instAllTypeBoundOp(c, n.info) proc setMagicType(conf: ConfigRef; m: PSym, kind: TTypeKind, size: int) = # source : https://en.wikipedia.org/wiki/Data_structure_alignment#x86 diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index e46ba937c..00c7cc558 100644 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -432,7 +432,6 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType = # adding myseq for myseq[system.int] # sigmatch: Formal myseq[=destroy.T] real myseq[system.int] #echo "DESTROY: adding ", typeToString(newbody), " for ", typeToString(result, preferDesc) - #cl.c.typesWithOps.add((newbody, result)) let mm = skipTypes(bbody, abstractPtrs) if tfFromGeneric notin mm.flags: # bug #5479, prevent endless recursions here: @@ -642,23 +641,6 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType = result.size = -1 result.n = replaceObjBranches(cl, result.n) -template typeBound(c, newty, oldty, field, info) = - let opr = newty.attachedOps[field] - if opr != nil and sfFromGeneric notin opr.flags: - # '=' needs to be instantiated for generics when the type is constructed: - #echo "DESTROY: instantiating ", astToStr(field), " for ", typeToString(oldty) - newty.attachedOps[field] = c.instTypeBoundOp(c, opr, oldty, info, attachedAsgn, 1) - -proc instAllTypeBoundOp*(c: PContext, info: TLineInfo) = - var i = 0 - while i < c.typesWithOps.len: - let (newty, oldty) = c.typesWithOps[i] - typeBound(c, newty, oldty, attachedDestructor, info) - typeBound(c, newty, oldty, attachedSink, info) - typeBound(c, newty, oldty, attachedAsgn, info) - inc i - setLen(c.typesWithOps, 0) - proc initTypeVars*(p: PContext, typeMap: LayeredIdTable, info: TLineInfo; owner: PSym): TReplTypeVars = initIdTable(result.symMap) diff --git a/compiler/transf.nim b/compiler/transf.nim index e9ab6b47d..daf223106 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -791,7 +791,7 @@ proc transformCall(c: PTransf, n: PNode): PNode = while (j < n.len): let b = transform(c, n[j]) if not isConstExpr(b): break - a = evalOp(op.magic, n, a, b, nil, c.graph) + a = evalOp(op.magic, n, a, b, nil, c.idgen, c.graph) inc(j) result.add(a) if result.len == 2: result = result[1] @@ -869,7 +869,7 @@ proc commonOptimizations*(g: ModuleGraph; idgen: IdGenerator; c: PSym, n: PNode) while j < args.len: let b = args[j] if not isConstExpr(b): break - a = evalOp(op.magic, result, a, b, nil, g) + a = evalOp(op.magic, result, a, b, nil, idgen, g) inc(j) result.add(a) if result.len == 2: result = result[1] |