explicit ID generation for easier IC (#15559)

* refactoring: idents don't need inheritance
* refactoring: adding an IdGenerator (part 1)
* refactoring: adding an IdGenerator (part 2)
* refactoring: adding an IdGenerator (part 3)
* refactoring: adding an IdGenerator (part 4)
* refactoring: adding an IdGenerator (part 5)
* refactoring: adding an IdGenerator (part 5)
* IdGenerator must be a ref type; hello world works again
* make bootstrapping work again
* progress: add back the 'exactReplica' ideas
* added back the missing exactReplica hacks
* make tcompilerapi work again
* make important packages green
* attempt to fix the build for 32 bit machines (probably need a better solution here)
This commit is contained in:
Andreas Rumpf 2020-10-25 08:50:47 +01:00 • committed by GitHub
commit 226595515c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
67 changed files with 853 additions and 903 deletions

View file

@ -53,9 +53,9 @@ proc typeNeedsNoDeepCopy(t: PType): bool =
if t.kind in {tyVar, tyLent, tySequence}: t = t.lastSon
result = not containsGarbageCollectedRef(t)
proc addLocalVar(g: ModuleGraph; varSection, varInit: PNode; owner: PSym; typ: PType;
proc addLocalVar(g: ModuleGraph; varSection, varInit: PNode; idgen: IdGenerator; owner: PSym; typ: PType;
v: PNode; useShallowCopy=false): PSym =
result = newSym(skTemp, getIdent(g.cache, genPrefix), owner, varSection.info,
result = newSym(skTemp, getIdent(g.cache, genPrefix), nextId idgen, owner, varSection.info,
owner.options)
result.typ = typ
incl(result.flags, sfFromGeneric)
@ -111,22 +111,23 @@ stmtList:
proc createWrapperProc(g: ModuleGraph; f: PNode; threadParam, argsParam: PSym;
varSection, varInit, call, barrier, fv: PNode;
idgen: IdGenerator;
spawnKind: TSpawnResult, result: PSym) =
var body = newNodeI(nkStmtList, f.info)
var threadLocalBarrier: PSym
if barrier != nil:
var varSection2 = newNodeI(nkVarSection, barrier.info)
threadLocalBarrier = addLocalVar(g, varSection2, nil, result,
threadLocalBarrier = addLocalVar(g, varSection2, nil, idgen, result,
barrier.typ, barrier)
body.add varSection2
body.add callCodegenProc(g, "barrierEnter", threadLocalBarrier.info,
threadLocalBarrier.newSymNode)
var threadLocalProm: PSym
if spawnKind == srByVar:
threadLocalProm = addLocalVar(g, varSection, nil, result, fv.typ, fv)
threadLocalProm = addLocalVar(g, varSection, nil, idgen, result, fv.typ, fv)
elif fv != nil:
internalAssert g.config, fv.typ.kind == tyGenericInst
threadLocalProm = addLocalVar(g, varSection, nil, result, fv.typ, fv)
threadLocalProm = addLocalVar(g, varSection, nil, idgen, result, fv.typ, fv)
body.add varSection
body.add varInit
if fv != nil and spawnKind != srByVar:
@ -168,7 +169,7 @@ proc createWrapperProc(g: ModuleGraph; f: PNode; threadParam, argsParam: PSym;
params.add threadParam.newSymNode
params.add argsParam.newSymNode
var t = newType(tyProc, threadParam.owner)
var t = newType(tyProc, nextId idgen, threadParam.owner)
t.rawAddSon nil
t.rawAddSon threadParam.typ
t.rawAddSon argsParam.typ
@ -184,15 +185,15 @@ proc createWrapperProc(g: ModuleGraph; f: PNode; threadParam, argsParam: PSym;
exceptions = emptyNode)
result.typ = t
proc createCastExpr(argsParam: PSym; objType: PType): PNode =
proc createCastExpr(argsParam: PSym; objType: PType; idgen: IdGenerator): PNode =
result = newNodeI(nkCast, argsParam.info)
result.add newNodeI(nkEmpty, argsParam.info)
result.add newSymNode(argsParam)
result.typ = newType(tyPtr, objType.owner)
result.typ = newType(tyPtr, nextId idgen, objType.owner)
result.typ.rawAddSon(objType)
proc setupArgsForConcurrency(g: ModuleGraph; n: PNode; objType: PType;
owner: PSym; scratchObj: PSym,
idgen: IdGenerator; owner: PSym; scratchObj: PSym,
castExpr, call,
varSection, varInit, result: PNode) =
let formals = n[0].typ.n
@ -210,16 +211,17 @@ proc setupArgsForConcurrency(g: ModuleGraph; n: PNode; objType: PType;
# localError(n[i].info, "'spawn'ed function cannot refer to 'ref'/closure")
let fieldname = if i < formals.len: formals[i].sym.name else: tmpName
var field = newSym(skField, fieldname, objType.owner, n.info, g.config.options)
var field = newSym(skField, fieldname, nextId idgen, objType.owner, n.info, g.config.options)
field.typ = argType
objType.addField(field, g.cache)
objType.addField(field, g.cache, idgen)
result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n[i])
let temp = addLocalVar(g, varSection, varInit, owner, argType,
let temp = addLocalVar(g, varSection, varInit, idgen, owner, argType,
indirectAccess(castExpr, field, n.info))
call.add(newSymNode(temp))
proc setupArgsForParallelism(g: ModuleGraph; n: PNode; objType: PType;
idgen: IdGenerator;
owner: PSym; scratchObj: PSym;
castExpr, call,
varSection, varInit, result: PNode) =
@ -237,7 +239,7 @@ proc setupArgsForParallelism(g: ModuleGraph; n: PNode; objType: PType;
# localError(n.info, "'spawn'ed function cannot refer to 'ref'/closure")
let fieldname = if i < formals.len: formals[i].sym.name else: tmpName
var field = newSym(skField, fieldname, objType.owner, n.info, g.config.options)
var field = newSym(skField, fieldname, nextId idgen, objType.owner, n.info, g.config.options)
if argType.kind in {tyVarargs, tyOpenArray}:
# important special case: we always create a zero-copy slice:
@ -245,30 +247,30 @@ proc setupArgsForParallelism(g: ModuleGraph; n: PNode; objType: PType;
slice.typ = n.typ
slice[0] = newSymNode(createMagic(g, "slice", mSlice))
slice[0].typ = getSysType(g, n.info, tyInt) # fake type
var fieldB = newSym(skField, tmpName, objType.owner, n.info, g.config.options)
var fieldB = newSym(skField, tmpName, nextId idgen, objType.owner, n.info, g.config.options)
fieldB.typ = getSysType(g, n.info, tyInt)
objType.addField(fieldB, g.cache)
objType.addField(fieldB, g.cache, idgen)
if getMagic(n) == mSlice:
let a = genAddrOf(n[1])
let a = genAddrOf(n[1], idgen)
field.typ = a.typ
objType.addField(field, g.cache)
objType.addField(field, g.cache, idgen)
result.add newFastAsgnStmt(newDotExpr(scratchObj, field), a)
var fieldA = newSym(skField, tmpName, objType.owner, n.info, g.config.options)
var fieldA = newSym(skField, tmpName, nextId idgen, objType.owner, n.info, g.config.options)
fieldA.typ = getSysType(g, n.info, tyInt)
objType.addField(fieldA, g.cache)
objType.addField(fieldA, g.cache, idgen)
result.add newFastAsgnStmt(newDotExpr(scratchObj, fieldA), n[2])
result.add newFastAsgnStmt(newDotExpr(scratchObj, fieldB), n[3])
let threadLocal = addLocalVar(g, varSection,nil, owner, fieldA.typ,
let threadLocal = addLocalVar(g, varSection, nil, idgen, owner, fieldA.typ,
indirectAccess(castExpr, fieldA, n.info),
useShallowCopy=true)
slice[2] = threadLocal.newSymNode
else:
let a = genAddrOf(n)
let a = genAddrOf(n, idgen)
field.typ = a.typ
objType.addField(field, g.cache)
objType.addField(field, g.cache, idgen)
result.add newFastAsgnStmt(newDotExpr(scratchObj, field), a)
result.add newFastAsgnStmt(newDotExpr(scratchObj, fieldB), genHigh(g, n))
@ -276,7 +278,7 @@ proc setupArgsForParallelism(g: ModuleGraph; n: PNode; objType: PType;
# the array itself does not need to go through a thread local variable:
slice[1] = genDeref(indirectAccess(castExpr, field, n.info))
let threadLocal = addLocalVar(g, varSection,nil, owner, fieldB.typ,
let threadLocal = addLocalVar(g, varSection, nil, idgen, owner, fieldB.typ,
indirectAccess(castExpr, fieldB, n.info),
useShallowCopy=true)
slice[3] = threadLocal.newSymNode
@ -284,26 +286,26 @@ proc setupArgsForParallelism(g: ModuleGraph; n: PNode; objType: PType;
elif (let size = computeSize(g.config, argType); size < 0 or size > 16) and
n.getRoot != nil:
# it is more efficient to pass a pointer instead:
let a = genAddrOf(n)
let a = genAddrOf(n, idgen)
field.typ = a.typ
objType.addField(field, g.cache)
objType.addField(field, g.cache, idgen)
result.add newFastAsgnStmt(newDotExpr(scratchObj, field), a)
let threadLocal = addLocalVar(g, varSection,nil, owner, field.typ,
let threadLocal = addLocalVar(g, varSection, nil, idgen, owner, field.typ,
indirectAccess(castExpr, field, n.info),
useShallowCopy=true)
call.add(genDeref(threadLocal.newSymNode))
else:
# boring case
field.typ = argType
objType.addField(field, g.cache)
objType.addField(field, g.cache, idgen)
result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n)
let threadLocal = addLocalVar(g, varSection, varInit,
owner, field.typ,
idgen, owner, field.typ,
indirectAccess(castExpr, field, n.info),
useShallowCopy=true)
call.add(threadLocal.newSymNode)
proc wrapProcForSpawn*(g: ModuleGraph; owner: PSym; spawnExpr: PNode; retType: PType;
proc wrapProcForSpawn*(g: ModuleGraph; idgen: IdGenerator; owner: PSym; spawnExpr: PNode; retType: PType;
barrier, dest: PNode = nil): PNode =
# if 'barrier' != nil, then it is in a 'parallel' section and we
# generate quite different code
@ -330,9 +332,9 @@ proc wrapProcForSpawn*(g: ModuleGraph; owner: PSym; spawnExpr: PNode; retType: P
var fn = n[0]
let
name = (if fn.kind == nkSym: fn.sym.name.s else: genPrefix) & "Wrapper"
wrapperProc = newSym(skProc, getIdent(g.cache, name), owner, fn.info, g.config.options)
threadParam = newSym(skParam, getIdent(g.cache, "thread"), wrapperProc, n.info, g.config.options)
argsParam = newSym(skParam, getIdent(g.cache, "args"), wrapperProc, n.info, g.config.options)
wrapperProc = newSym(skProc, getIdent(g.cache, name), nextId idgen, owner, fn.info, g.config.options)
threadParam = newSym(skParam, getIdent(g.cache, "thread"), nextId idgen, wrapperProc, n.info, g.config.options)
argsParam = newSym(skParam, getIdent(g.cache, "args"), nextId idgen, wrapperProc, n.info, g.config.options)
wrapperProc.flags.incl sfInjectDestructors
block:
@ -341,11 +343,11 @@ proc wrapProcForSpawn*(g: ModuleGraph; owner: PSym; spawnExpr: PNode; retType: P
argsParam.typ = ptrType
argsParam.position = 1
var objType = createObj(g, owner, n.info)
var objType = createObj(g, idgen, owner, n.info)
incl(objType.flags, tfFinal)
let castExpr = createCastExpr(argsParam, objType)
let castExpr = createCastExpr(argsParam, objType, idgen)
var scratchObj = newSym(skVar, getIdent(g.cache, "scratch"), owner, n.info, g.config.options)
var scratchObj = newSym(skVar, getIdent(g.cache, "scratch"), nextId idgen, owner, n.info, g.config.options)
block:
scratchObj.typ = objType
incl(scratchObj.flags, sfFromGeneric)
@ -362,9 +364,9 @@ proc wrapProcForSpawn*(g: ModuleGraph; owner: PSym; spawnExpr: PNode; retType: P
skFunc, skMethod, skConverter}):
# for indirect calls we pass the function pointer in the scratchObj
var argType = n[0].typ.skipTypes(abstractInst)
var field = newSym(skField, getIdent(g.cache, "fn"), owner, n.info, g.config.options)
var field = newSym(skField, getIdent(g.cache, "fn"), nextId idgen, owner, n.info, g.config.options)
field.typ = argType
objType.addField(field, g.cache)
objType.addField(field, g.cache, idgen)
result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n[0])
fn = indirectAccess(castExpr, field, n.info)
elif fn.kind == nkSym and fn.sym.kind == skIterator:
@ -376,49 +378,48 @@ proc wrapProcForSpawn*(g: ModuleGraph; owner: PSym; spawnExpr: PNode; retType: P
var varSection = newNodeI(nkVarSection, n.info)
var varInit = newNodeI(nkStmtList, n.info)
if barrier.isNil:
setupArgsForConcurrency(g, n, objType, wrapperProc, scratchObj, castExpr, call,
setupArgsForConcurrency(g, n, objType, idgen, wrapperProc, scratchObj, castExpr, call,
varSection, varInit, result)
else:
setupArgsForParallelism(g, n, objType, wrapperProc, scratchObj, castExpr, call,
setupArgsForParallelism(g, n, objType, idgen, wrapperProc, scratchObj, castExpr, call,
varSection, varInit, result)
var barrierAsExpr: PNode = nil
if barrier != nil:
let typ = newType(tyPtr, owner)
let typ = newType(tyPtr, nextId idgen, owner)
typ.rawAddSon(magicsys.getCompilerProc(g, "Barrier").typ)
var field = newSym(skField, getIdent(g.cache, "barrier"), owner, n.info, g.config.options)
var field = newSym(skField, getIdent(g.cache, "barrier"), nextId idgen, owner, n.info, g.config.options)
field.typ = typ
objType.addField(field, g.cache)
objType.addField(field, g.cache, idgen)
result.add newFastAsgnStmt(newDotExpr(scratchObj, field), barrier)
barrierAsExpr = indirectAccess(castExpr, field, n.info)
var fvField, fvAsExpr: PNode = nil
if spawnKind == srFlowVar:
var field = newSym(skField, getIdent(g.cache, "fv"), owner, n.info, g.config.options)
var field = newSym(skField, getIdent(g.cache, "fv"), nextId idgen, owner, n.info, g.config.options)
field.typ = retType
objType.addField(field, g.cache)
objType.addField(field, g.cache, idgen)
fvField = newDotExpr(scratchObj, field)
fvAsExpr = indirectAccess(castExpr, field, n.info)
# create flowVar:
result.add newFastAsgnStmt(fvField, callProc(spawnExpr[^1]))
if barrier == nil:
result.add callCodegenProc(g, "nimFlowVarCreateSemaphore", fvField.info,
fvField)
result.add callCodegenProc(g, "nimFlowVarCreateSemaphore", fvField.info, fvField)
elif spawnKind == srByVar:
var field = newSym(skField, getIdent(g.cache, "fv"), owner, n.info, g.config.options)
field.typ = newType(tyPtr, objType.owner)
var field = newSym(skField, getIdent(g.cache, "fv"), nextId idgen, owner, n.info, g.config.options)
field.typ = newType(tyPtr, nextId idgen, objType.owner)
field.typ.rawAddSon(retType)
objType.addField(field, g.cache)
objType.addField(field, g.cache, idgen)
fvAsExpr = indirectAccess(castExpr, field, n.info)
result.add newFastAsgnStmt(newDotExpr(scratchObj, field), genAddrOf(dest))
result.add newFastAsgnStmt(newDotExpr(scratchObj, field), genAddrOf(dest, idgen))
createTypeBoundOps(g, nil, objType, n.info)
createTypeBoundOps(g, nil, objType, n.info, idgen)
createWrapperProc(g, fn, threadParam, argsParam,
varSection, varInit, call,
barrierAsExpr, fvAsExpr, spawnKind, wrapperProc)
barrierAsExpr, fvAsExpr, idgen, spawnKind, wrapperProc)
result.add callCodegenProc(g, "nimSpawn" & $spawnExpr.len, wrapperProc.info,
wrapperProc.newSymNode, genAddrOf(scratchObj.newSymNode), nil, spawnExpr)
wrapperProc.newSymNode, genAddrOf(scratchObj.newSymNode, idgen), nil, spawnExpr)
if spawnKind == srFlowVar: result.add fvField