Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 61 additions & 32 deletions compiler/ast.nim
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
# abstract syntax tree + symbol table

import
lineinfos, hashes, options, ropes, idents, idgen, int128
lineinfos, hashes, options, ropes, idents, int128
from strutils import toLowerAscii

export int128
Expand Down Expand Up @@ -717,6 +717,14 @@ const
mInSet, mRepr}

type
ItemId* = object
module*: int32
item*: int32

TIdObj* = object of RootObj
itemId*: ItemId
PIdObj* = ref TIdObj

PNode* = ref TNode
TNodeSeq* = seq[PNode]
PType* = ref TType
Expand Down Expand Up @@ -926,7 +934,7 @@ type
loc*: TLoc
typeInst*: PType # for generic instantiations the tyGenericInst that led to this
# type.
uniqueId*: int # due to a design mistake, we need to keep the real ID here as it
uniqueId*: ItemId # due to a design mistake, we need to keep the real ID here as it
# required by the --incremental:on mode.

TPair* = object
Expand Down Expand Up @@ -1060,6 +1068,35 @@ proc getnimblePkg*(a: PSym): PSym =
else:
assert false, $result.kind

const
moduleShift = when defined(cpu32): 20 else: 24

template id*(a: PIdObj): int =
let x = a
(x.itemId.module.int shl moduleShift) + x.itemId.item.int

type
IdGenerator* = ref ItemId # unfortunately, we really need the 'shared mutable' aspect here.

const
PackageModuleId* = -3'i32

proc idGeneratorFromModule*(m: PSym): IdGenerator =
assert m.kind == skModule
result = IdGenerator(module: m.itemId.module, item: m.itemId.item)

proc nextId*(x: IdGenerator): ItemId {.inline.} =
inc x.item
result = x[]

when false:
proc storeBack*(dest: var IdGenerator; src: IdGenerator) {.inline.} =
assert dest.ItemId.module == src.ItemId.module
if dest.ItemId.item > src.ItemId.item:
echo dest.ItemId.item, " ", src.ItemId.item, " ", src.ItemId.module
assert dest.ItemId.item <= src.ItemId.item
dest = src

proc getnimblePkgId*(a: PSym): int =
let b = a.getnimblePkg
result = if b == nil: -1 else: b.id
Expand Down Expand Up @@ -1164,13 +1201,11 @@ proc newTreeIT*(kind: TNodeKind; info: TLineInfo; typ: PType; children: varargs[
template previouslyInferred*(t: PType): PType =
if t.sons.len > 1: t.lastSon else: nil

proc newSym*(symKind: TSymKind, name: PIdent, owner: PSym,
proc newSym*(symKind: TSymKind, name: PIdent, id: ItemId, owner: PSym,
info: TLineInfo; options: TOptions = {}): PSym =
# generates a symbol and initializes the hash field too
result = PSym(name: name, kind: symKind, flags: {}, info: info, id: getID(),
result = PSym(name: name, kind: symKind, flags: {}, info: info, itemId: id,
options: options, owner: owner, offset: defaultOffset)
when debugIds:
registerId(result)

proc astdef*(s: PSym): PNode =
# get only the definition (initializer) portion of the ast
Expand Down Expand Up @@ -1344,13 +1379,11 @@ proc `$`*(s: PSym): string =
else:
result = "<nil>"

proc newType*(kind: TTypeKind, owner: PSym): PType =
let id = getID()
proc newType*(kind: TTypeKind, id: ItemId; owner: PSym): PType =
result = PType(kind: kind, owner: owner, size: defaultSize,
align: defaultAlignment, id: id, uniqueId: id,
lockLevel: UnspecifiedLockLevel)
when debugIds:
registerId(result)
align: defaultAlignment, itemId: id,
lockLevel: UnspecifiedLockLevel,
uniqueId: id)
when false:
if result.id == 76426:
echo "KNID ", kind
Expand Down Expand Up @@ -1392,22 +1425,18 @@ proc assignType*(dest, src: PType) =
newSons(dest, src.len)
for i in 0..<src.len: dest[i] = src[i]

proc copyType*(t: PType, owner: PSym, keepId: bool): PType =
result = newType(t.kind, owner)
proc copyType*(t: PType, id: ItemId, owner: PSym): PType =
result = newType(t.kind, id, owner)
assignType(result, t)
if keepId:
result.id = t.id
else:
when debugIds: registerId(result)
result.sym = t.sym # backend-info should not be copied

proc exactReplica*(t: PType): PType = copyType(t, t.owner, true)
proc exactReplica*(t: PType): PType =
result = copyType(t, t.itemId, t.owner)

proc copySym*(s: PSym): PSym =
result = newSym(s.kind, s.name, s.owner, s.info, s.options)
proc copySym*(s: PSym; id: ItemId): PSym =
result = newSym(s.kind, s.name, id, s.owner, s.info, s.options)
#result.ast = nil # BUGFIX; was: s.ast which made problems
result.typ = s.typ
when debugIds: registerId(result)
result.flags = s.flags
result.magic = s.magic
if s.kind == skModule:
Expand All @@ -1421,12 +1450,12 @@ proc copySym*(s: PSym): PSym =
result.bitsize = s.bitsize
result.alignment = s.alignment

proc createModuleAlias*(s: PSym, newIdent: PIdent, info: TLineInfo;
proc createModuleAlias*(s: PSym, id: ItemId, newIdent: PIdent, info: TLineInfo;
options: TOptions): PSym =
result = newSym(s.kind, newIdent, s.owner, info, options)
result = newSym(s.kind, newIdent, id, s.owner, info, options)
# keep ID!
result.ast = s.ast
result.id = s.id
#result.id = s.id # XXX figure out what to do with the ID.
result.flags = s.flags
system.shallowCopy(result.tab, s.tab)
result.options = s.options
Expand Down Expand Up @@ -1576,7 +1605,7 @@ proc transitionNoneToSym*(n: PNode) =

template transitionSymKindCommon*(k: TSymKind) =
let obj {.inject.} = s[]
s[] = TSym(kind: k, id: obj.id, magic: obj.magic, typ: obj.typ, name: obj.name,
s[] = TSym(kind: k, itemId: obj.itemId, magic: obj.magic, typ: obj.typ, name: obj.name,
info: obj.info, owner: obj.owner, flags: obj.flags, ast: obj.ast,
options: obj.options, position: obj.position, offset: obj.offset,
loc: obj.loc, annex: obj.annex, constraint: obj.constraint)
Expand Down Expand Up @@ -1797,19 +1826,19 @@ proc skipStmtList*(n: PNode): PNode =
else:
result = n

proc toVar*(typ: PType; kind: TTypeKind): PType =
proc toVar*(typ: PType; kind: TTypeKind; idgen: IdGenerator): PType =
## If ``typ`` is not a tyVar then it is converted into a `var <typ>` and
## returned. Otherwise ``typ`` is simply returned as-is.
result = typ
if typ.kind != kind:
result = newType(kind, typ.owner)
result = newType(kind, nextId(idgen), typ.owner)
rawAddSon(result, typ)

proc toRef*(typ: PType): PType =
proc toRef*(typ: PType; idgen: IdGenerator): PType =
## If ``typ`` is a tyObject then it is converted into a `ref <typ>` and
## returned. Otherwise ``typ`` is simply returned as-is.
if typ.skipTypes({tyAlias, tyGenericInst}).kind == tyObject:
result = newType(tyRef, typ.owner)
result = newType(tyRef, nextId(idgen), typ.owner)
rawAddSon(result, typ)

proc toObject*(typ: PType): PType =
Expand Down Expand Up @@ -1888,8 +1917,8 @@ proc isSinkParam*(s: PSym): bool {.inline.} =
proc isSinkType*(t: PType): bool {.inline.} =
t.kind == tySink or tfHasOwned in t.flags

proc newProcType*(info: TLineInfo; owner: PSym): PType =
result = newType(tyProc, owner)
proc newProcType*(info: TLineInfo; id: ItemId; owner: PSym): PType =
result = newType(tyProc, id, owner)
result.n = newNodeI(nkFormalParams, info)
rawAddSon(result, nil) # return type
# result.n[0] used to be `nkType`, but now it's `nkEffectList` because
Expand Down
20 changes: 10 additions & 10 deletions compiler/ccgexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1765,20 +1765,20 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
else: putIntoDest(p, d, e, rope(lengthOrd(p.config, typ)))
else: internalError(p.config, e.info, "genArrayLen()")

proc makePtrType(baseType: PType): PType =
result = newType(tyPtr, baseType.owner)
addSonSkipIntLit(result, baseType)
proc makePtrType(baseType: PType; idgen: IdGenerator): PType =
result = newType(tyPtr, nextId idgen, baseType.owner)
addSonSkipIntLit(result, baseType, idgen)

proc makeAddr(n: PNode): PNode =
proc makeAddr(n: PNode; idgen: IdGenerator): PNode =
if n.kind == nkHiddenAddr:
result = n
else:
result = newTree(nkHiddenAddr, n)
result.typ = makePtrType(n.typ)
result.typ = makePtrType(n.typ, idgen)

proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) =
if optSeqDestructors in p.config.globalOptions:
e[1] = makeAddr(e[1])
e[1] = makeAddr(e[1], p.module.idgen)
genCall(p, e, d)
return
var a, b, call: TLoc
Expand Down Expand Up @@ -2240,7 +2240,7 @@ proc genEnumToStr(p: BProc, e: PNode, d: var TLoc) =
toStrProc = p
break
if toStrProc == nil:
toStrProc = genEnumToStrProc(t, e.info, p.module.g.graph)
toStrProc = genEnumToStrProc(t, e.info, p.module.g.graph, p.module.idgen)
t.methods.add((ToStringProcSlot, toStrProc))
var n = copyTree(e)
n[0] = newSymNode(toStrProc)
Expand Down Expand Up @@ -2294,7 +2294,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
of mAppendStrStr: genStrAppend(p, e, d)
of mAppendSeqElem:
if optSeqDestructors in p.config.globalOptions:
e[1] = makeAddr(e[1])
e[1] = makeAddr(e[1], p.module.idgen)
genCall(p, e, d)
else:
genSeqElemAppend(p, e, d)
Expand Down Expand Up @@ -2393,13 +2393,13 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
when defined(leanCompiler):
quit "compiler built without support for the 'spawn' statement"
else:
let n = spawn.wrapProcForSpawn(p.module.g.graph, p.module.module, e, e.typ, nil, nil)
let n = spawn.wrapProcForSpawn(p.module.g.graph, p.module.idgen, p.module.module, e, e.typ, nil, nil)
expr(p, n, d)
of mParallel:
when defined(leanCompiler):
quit "compiler built without support for the 'parallel' statement"
else:
let n = semparallel.liftParallel(p.module.g.graph, p.module.module, e)
let n = semparallel.liftParallel(p.module.g.graph, p.module.idgen, p.module.module, e)
expr(p, n, d)
of mDeepCopy:
if p.config.selectedGC in {gcArc, gcOrc} and optEnableDeepCopy notin p.config.globalOptions:
Expand Down
9 changes: 1 addition & 8 deletions compiler/ccgmerge.nim
Original file line number Diff line number Diff line change
Expand Up @@ -180,10 +180,6 @@ proc readKey(L: var TBaseLexer, result: var string) =
if L.buf[pos] != ':': doAssert(false, "ccgmerge: ':' expected")
L.bufpos = pos + 1 # skip ':'

proc newFakeType(id: int): PType =
new(result)
result.id = id

proc readTypeCache(L: var TBaseLexer, result: var TypeCache) =
if ^L.bufpos != '{': doAssert(false, "ccgmerge: '{' expected")
inc L.bufpos
Expand All @@ -192,10 +188,7 @@ proc readTypeCache(L: var TBaseLexer, result: var TypeCache) =
var key = decodeStr(L.buf, L.bufpos)
if ^L.bufpos != ':': doAssert(false, "ccgmerge: ':' expected")
inc L.bufpos
var value = decodeStr(L.buf, L.bufpos)
# XXX implement me
when false:
idTablePut(result, newFakeType(key), value.rope)
discard decodeStr(L.buf, L.bufpos)
inc L.bufpos

proc readIntSet(L: var TBaseLexer, result: var IntSet) =
Expand Down
4 changes: 2 additions & 2 deletions compiler/ccgstmts.nim
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ proc genVarTuple(p: BProc, n: PNode) =
# if we have a something that's been captured, use the lowering instead:
for i in 0..<n.len-2:
if n[i].kind != nkSym:
genStmts(p, lowerTupleUnpacking(p.module.g.graph, n, p.prc))
genStmts(p, lowerTupleUnpacking(p.module.g.graph, n, p.module.idgen, p.prc))
return

# check only the first son
Expand Down Expand Up @@ -1525,7 +1525,7 @@ proc genCaseObjDiscMapping(p: BProc, e: PNode, t: PType, field: PSym; d: var TLo
theProc = p
break
if theProc == nil:
theProc = genCaseObjDiscMapping(t, field, e.info, p.module.g.graph)
theProc = genCaseObjDiscMapping(t, field, e.info, p.module.g.graph, p.module.idgen)
t.methods.add((ObjDiscMappingProcSlot, theProc))
var call = newNodeIT(nkCall, e.info, getSysType(p.module.g.graph, e.info, tyUInt8))
call.add newSymNode(theProc)
Expand Down
14 changes: 7 additions & 7 deletions compiler/ccgtypes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1266,10 +1266,10 @@ proc genArrayInfo(m: BModule, typ: PType, name: Rope; info: TLineInfo) =

proc fakeClosureType(m: BModule; owner: PSym): PType =
# we generate the same RTTI as for a tuple[pointer, ref tuple[]]
result = newType(tyTuple, owner)
result.rawAddSon(newType(tyPointer, owner))
var r = newType(tyRef, owner)
let obj = createObj(m.g.graph, owner, owner.info, final=false)
result = newType(tyTuple, nextId m.idgen, owner)
result.rawAddSon(newType(tyPointer, nextId m.idgen, owner))
var r = newType(tyRef, nextId m.idgen, owner)
let obj = createObj(m.g.graph, m.idgen, owner, owner.info, final=false)
r.rawAddSon(obj)
result.rawAddSon(r)

Expand Down Expand Up @@ -1395,9 +1395,9 @@ proc genTypeInfoV2(m: BModule, t: PType; info: TLineInfo): Rope =
result = prefixTI.rope & result & ")".rope

proc openArrayToTuple(m: BModule; t: PType): PType =
result = newType(tyTuple, t.owner)
let p = newType(tyPtr, t.owner)
let a = newType(tyUncheckedArray, t.owner)
result = newType(tyTuple, nextId m.idgen, t.owner)
let p = newType(tyPtr, nextId m.idgen, t.owner)
let a = newType(tyUncheckedArray, nextId m.idgen, t.owner)
a.add t.lastSon
p.add a
result.add p
Expand Down
11 changes: 6 additions & 5 deletions compiler/cgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -996,9 +996,9 @@ proc genProcAux(m: BModule, prc: PSym) =
var returnStmt: Rope = nil
assert(prc.ast != nil)

var procBody = transformBody(m.g.graph, prc, cache = false)
var procBody = transformBody(m.g.graph, m.idgen, prc, cache = false)
if sfInjectDestructors in prc.flags:
procBody = injectDestructorCalls(m.g.graph, prc, procBody)
procBody = injectDestructorCalls(m.g.graph, m.idgen, prc, procBody)

if sfPure notin prc.flags and prc.typ[0] != nil:
if resultPos >= prc.ast.len:
Expand Down Expand Up @@ -1844,9 +1844,10 @@ template injectG() {.dirty.} =
when not defined(nimHasSinkInference):
{.pragma: nosinks.}

proc myOpen(graph: ModuleGraph; module: PSym): PPassContext {.nosinks.} =
proc myOpen(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext {.nosinks.} =
injectG()
result = newModule(g, module, graph.config)
result.idgen = idgen
if optGenIndex in graph.config.globalOptions and g.generatedHeader == nil:
let f = if graph.config.headerFile.len > 0: AbsoluteFile graph.config.headerFile
else: graph.config.projectFull
Expand Down Expand Up @@ -1920,9 +1921,9 @@ proc myProcess(b: PPassContext, n: PNode): PNode =
m.initProc.options = initProcOptions(m)
#softRnl = if optLineDir in m.config.options: noRnl else: rnl
# XXX replicate this logic!
var transformedN = transformStmt(m.g.graph, m.module, n)
var transformedN = transformStmt(m.g.graph, m.idgen, m.module, n)
if sfInjectDestructors in m.module.flags:
transformedN = injectDestructorCalls(m.g.graph, m.module, transformedN)
transformedN = injectDestructorCalls(m.g.graph, m.idgen, m.module, transformedN)

if m.hcrOn:
addHcrInitGuards(m.initProc, transformedN, m.inHcrInitGuard)
Expand Down
12 changes: 6 additions & 6 deletions compiler/cgmeth.nim
Original file line number Diff line number Diff line change
Expand Up @@ -107,19 +107,19 @@ proc attachDispatcher(s: PSym, dispatcher: PNode) =
s.ast[resultPos] = newNodeI(nkEmpty, s.info)
s.ast[dispatcherPos] = dispatcher

proc createDispatcher(s: PSym): PSym =
var disp = copySym(s)
proc createDispatcher(s: PSym; idgen: IdGenerator): PSym =
var disp = copySym(s, nextId(idgen))
incl(disp.flags, sfDispatcher)
excl(disp.flags, sfExported)
disp.typ = copyType(disp.typ, disp.typ.owner, false)
disp.typ = copyType(disp.typ, nextId(idgen), disp.typ.owner)
# we can't inline the dispatcher itself (for now):
if disp.typ.callConv == ccInline: disp.typ.callConv = ccNimCall
disp.ast = copyTree(s.ast)
disp.ast[bodyPos] = newNodeI(nkEmpty, s.info)
disp.loc.r = nil
if s.typ[0] != nil:
if disp.ast.len > resultPos:
disp.ast[resultPos].sym = copySym(s.ast[resultPos].sym)
disp.ast[resultPos].sym = copySym(s.ast[resultPos].sym, nextId(idgen))
else:
# We've encountered a method prototype without a filled-in
# resultPos slot. We put a placeholder in there that will
Expand Down Expand Up @@ -157,7 +157,7 @@ proc fixupDispatcher(meth, disp: PSym; conf: ConfigRef) =
if disp.typ.lockLevel < meth.typ.lockLevel:
disp.typ.lockLevel = meth.typ.lockLevel

proc methodDef*(g: ModuleGraph; s: PSym, fromCache: bool) =
proc methodDef*(g: ModuleGraph; idgen: IdGenerator; s: PSym, fromCache: bool) =
var witness: PSym
for i in 0..<g.methods.len:
let disp = g.methods[i].dispatcher
Expand All @@ -177,7 +177,7 @@ proc methodDef*(g: ModuleGraph; s: PSym, fromCache: bool) =
of Invalid:
if witness.isNil: witness = g.methods[i].methods[0]
# create a new dispatcher:
g.methods.add((methods: @[s], dispatcher: createDispatcher(s)))
g.methods.add((methods: @[s], dispatcher: createDispatcher(s, idgen)))
#echo "adding ", s.info
#if fromCache:
# internalError(s.info, "no method dispatcher found")
Expand Down
Loading