diff options
Diffstat (limited to 'compiler/lowerings.nim')
-rw-r--r-- | compiler/lowerings.nim | 146 |
1 files changed, 71 insertions, 75 deletions
diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim index b3b6cbb5c..2c9c4cb32 100644 --- a/compiler/lowerings.nim +++ b/compiler/lowerings.nim @@ -15,8 +15,11 @@ const import ast, astalgo, types, idents, magicsys, msgs, options, modulegraphs, lineinfos +when defined(nimPreviewSlimSystem): + import std/assertions + proc newDeref*(n: PNode): PNode {.inline.} = - result = newNodeIT(nkHiddenDeref, n.info, n.typ[0]) + result = newNodeIT(nkHiddenDeref, n.info, n.typ.elementType) result.add n proc newTupleAccess*(g: ModuleGraph; tup: PNode, i: int): PNode = @@ -59,30 +62,46 @@ proc newFastAsgnStmt*(le, ri: PNode): PNode = result[0] = le result[1] = ri -proc lowerTupleUnpacking*(g: ModuleGraph; n: PNode; owner: PSym): PNode = +proc newFastMoveStmt*(g: ModuleGraph, le, ri: PNode): PNode = + result = newNodeI(nkFastAsgn, le.info, 2) + result[0] = le + result[1] = newNodeIT(nkCall, ri.info, ri.typ) + result[1].add newSymNode(getSysMagic(g, ri.info, "move", mMove)) + result[1].add ri + +proc lowerTupleUnpacking*(g: ModuleGraph; n: PNode; idgen: IdGenerator; owner: PSym): PNode = assert n.kind == nkVarTuple let value = n.lastSon result = newNodeI(nkStmtList, n.info) - var temp = newSym(skTemp, getIdent(g.cache, genPrefix), owner, value.info, g.config.options) - temp.typ = skipTypes(value.typ, abstractInst) - incl(temp.flags, sfFromGeneric) + var tempAsNode: PNode + let avoidTemp = value.kind == nkSym + if avoidTemp: + tempAsNode = value + else: + var temp = newSym(skTemp, getIdent(g.cache, genPrefix), idgen, + owner, value.info, g.config.options) + temp.typ = skipTypes(value.typ, abstractInst) + incl(temp.flags, sfFromGeneric) + tempAsNode = newSymNode(temp) var v = newNodeI(nkVarSection, value.info) - let tempAsNode = newSymNode(temp) - v.addVar(tempAsNode, value) + if not avoidTemp: + v.addVar(tempAsNode, value) result.add(v) for i in 0..<n.len-2: - if n[i].kind == nkSym: v.addVar(n[i]) - result.add newAsgnStmt(n[i], newTupleAccess(g, tempAsNode, i)) + let val = newTupleAccess(g, tempAsNode, i) + if n[i].kind == nkSym: v.addVar(n[i], val) + else: result.add newAsgnStmt(n[i], val) -proc evalOnce*(g: ModuleGraph; value: PNode; owner: PSym): PNode = +proc evalOnce*(g: ModuleGraph; value: PNode; idgen: IdGenerator; owner: PSym): PNode = ## Turns (value) into (let tmp = value; tmp) so that 'value' can be re-used ## freely, multiple times. This is frequently required and such a builtin would also be ## handy to have in macros.nim. The value that can be reused is 'result.lastSon'! result = newNodeIT(nkStmtListExpr, value.info, value.typ) - var temp = newSym(skTemp, getIdent(g.cache, genPrefix), owner, value.info, g.config.options) + var temp = newSym(skTemp, getIdent(g.cache, genPrefix), idgen, + owner, value.info, g.config.options) temp.typ = skipTypes(value.typ, abstractInst) incl(temp.flags, sfFromGeneric) @@ -103,31 +122,13 @@ proc newTupleAccessRaw*(tup: PNode, i: int): PNode = proc newTryFinally*(body, final: PNode): PNode = result = newTree(nkHiddenTryStmt, body, newTree(nkFinally, final)) -proc lowerTupleUnpackingForAsgn*(g: ModuleGraph; n: PNode; owner: PSym): PNode = - let value = n.lastSon - result = newNodeI(nkStmtList, n.info) - - var temp = newSym(skTemp, getIdent(g.cache, "_"), owner, value.info, owner.options) - var v = newNodeI(nkLetSection, value.info) - let tempAsNode = newSymNode(temp) #newIdentNode(getIdent(genPrefix & $temp.id), value.info) - - var vpart = newNodeI(nkIdentDefs, tempAsNode.info, 3) - vpart[0] = tempAsNode - vpart[1] = newNodeI(nkEmpty, value.info) - vpart[2] = value - v.add vpart - result.add(v) - - let lhs = n[0] - for i in 0..<lhs.len: - result.add newAsgnStmt(lhs[i], newTupleAccessRaw(tempAsNode, i)) - -proc lowerSwap*(g: ModuleGraph; n: PNode; owner: PSym): PNode = +proc lowerSwap*(g: ModuleGraph; n: PNode; idgen: IdGenerator; owner: PSym): PNode = result = newNodeI(nkStmtList, n.info) # note: cannot use 'skTemp' here cause we really need the copy for the VM :-( - var temp = newSym(skVar, getIdent(g.cache, genPrefix), owner, n.info, owner.options) + var temp = newSym(skVar, getIdent(g.cache, genPrefix), idgen, owner, n.info, owner.options) temp.typ = n[1].typ incl(temp.flags, sfFromGeneric) + incl(temp.flags, sfGenSym) var v = newNodeI(nkVarSection, n.info) let tempAsNode = newSymNode(temp) @@ -142,16 +143,16 @@ proc lowerSwap*(g: ModuleGraph; n: PNode; owner: PSym): PNode = result.add newFastAsgnStmt(n[1], n[2]) result.add newFastAsgnStmt(n[2], tempAsNode) -proc createObj*(g: ModuleGraph; owner: PSym, info: TLineInfo; final=true): PType = - result = newType(tyObject, owner) +proc createObj*(g: ModuleGraph; idgen: IdGenerator; owner: PSym, info: TLineInfo; final=true): PType = + result = newType(tyObject, idgen, owner) if final: rawAddSon(result, nil) incl result.flags, tfFinal else: rawAddSon(result, getCompilerProc(g, "RootObj").typ) result.n = newNodeI(nkRecList, info) - let s = newSym(skType, getIdent(g.cache, "Env_" & toFilename(g.config, info)), - owner, info, owner.options) + let s = newSym(skType, getIdent(g.cache, "Env_" & toFilename(g.config, info) & "_" & $owner.name.s), + idgen, owner, info, owner.options) incl s.flags, sfAnon s.typ = result result.sym = s @@ -188,7 +189,7 @@ proc rawDirectAccess*(obj, field: PSym): PNode = result.add newSymNode(field) result.typ = field.typ -proc lookupInRecord(n: PNode, id: int): PSym = +proc lookupInRecord(n: PNode, id: ItemId): PSym = result = nil case n.kind of nkRecList: @@ -206,31 +207,36 @@ proc lookupInRecord(n: PNode, id: int): PSym = if result != nil: return else: discard of nkSym: - if n.sym.id == -abs(id): result = n.sym + if n.sym.itemId.module == id.module and n.sym.itemId.item == -abs(id.item): result = n.sym else: discard -proc addField*(obj: PType; s: PSym; cache: IdentCache) = +proc addField*(obj: PType; s: PSym; cache: IdentCache; idgen: IdGenerator): PSym = # because of 'gensym' support, we have to mangle the name with its ID. # This is hacky but the clean solution is much more complex than it looks. - var field = newSym(skField, getIdent(cache, s.name.s & $obj.n.len), s.owner, s.info, - s.options) - field.id = -s.id - let t = skipIntLit(s.typ) + var field = newSym(skField, getIdent(cache, s.name.s & $obj.n.len), + idgen, s.owner, s.info, s.options) + field.itemId = ItemId(module: s.itemId.module, item: -s.itemId.item) + let t = skipIntLit(s.typ, idgen) field.typ = t + if s.kind in {skLet, skVar, skField, skForVar}: + #field.bitsize = s.bitsize + field.alignment = s.alignment assert t.kind != tyTyped propagateToOwner(obj, t) field.position = obj.n.len - field.flags = s.flags * {sfCursor} + # sfNoInit flag for skField is used in closureiterator codegen + field.flags = s.flags * {sfCursor, sfNoInit} obj.n.add newSymNode(field) fieldCheck() + result = field -proc addUniqueField*(obj: PType; s: PSym; cache: IdentCache): PSym {.discardable.} = - result = lookupInRecord(obj.n, s.id) +proc addUniqueField*(obj: PType; s: PSym; cache: IdentCache; idgen: IdGenerator): PSym {.discardable.} = + result = lookupInRecord(obj.n, s.itemId) if result == nil: - var field = newSym(skField, getIdent(cache, s.name.s & $obj.n.len), s.owner, s.info, - s.options) - field.id = -s.id - let t = skipIntLit(s.typ) + var field = newSym(skField, getIdent(cache, s.name.s & $obj.n.len), idgen, + s.owner, s.info, s.options) + field.itemId = ItemId(module: s.itemId.module, item: -s.itemId.item) + let t = skipIntLit(s.typ, idgen) field.typ = t assert t.kind != tyTyped propagateToOwner(obj, t) @@ -240,23 +246,23 @@ proc addUniqueField*(obj: PType; s: PSym; cache: IdentCache): PSym {.discardable proc newDotExpr*(obj, b: PSym): PNode = result = newNodeI(nkDotExpr, obj.info) - let field = lookupInRecord(obj.typ.n, b.id) + let field = lookupInRecord(obj.typ.n, b.itemId) assert field != nil, b.name.s result.add newSymNode(obj) result.add newSymNode(field) result.typ = field.typ -proc indirectAccess*(a: PNode, b: int, info: TLineInfo): PNode = +proc indirectAccess*(a: PNode, b: ItemId, info: TLineInfo): PNode = # returns a[].b as a node var deref = newNodeI(nkHiddenDeref, info) - deref.typ = a.typ.skipTypes(abstractInst)[0] + deref.typ = a.typ.skipTypes(abstractInst).elementType var t = deref.typ.skipTypes(abstractInst) var field: PSym while true: assert t.kind == tyObject field = lookupInRecord(t.n, b) if field != nil: break - t = t[0] + t = t.baseClass if t == nil: break t = t.skipTypes(skipPtrs) #if field == nil: @@ -272,7 +278,7 @@ proc indirectAccess*(a: PNode, b: int, info: TLineInfo): PNode = proc indirectAccess*(a: PNode, b: string, info: TLineInfo; cache: IdentCache): PNode = # returns a[].b as a node var deref = newNodeI(nkHiddenDeref, info) - deref.typ = a.typ.skipTypes(abstractInst)[0] + deref.typ = a.typ.skipTypes(abstractInst).elementType var t = deref.typ.skipTypes(abstractInst) var field: PSym let bb = getIdent(cache, b) @@ -280,7 +286,7 @@ proc indirectAccess*(a: PNode, b: string, info: TLineInfo; cache: IdentCache): P assert t.kind == tyObject field = getSymFromList(t.n, bb) if field != nil: break - t = t[0] + t = t.baseClass if t == nil: break t = t.skipTypes(skipPtrs) #if field == nil: @@ -298,33 +304,34 @@ proc getFieldFromObj*(t: PType; v: PSym): PSym = var t = t while true: assert t.kind == tyObject - result = lookupInRecord(t.n, v.id) + result = lookupInRecord(t.n, v.itemId) if result != nil: break - t = t[0] + t = t.baseClass if t == nil: break t = t.skipTypes(skipPtrs) proc indirectAccess*(a: PNode, b: PSym, info: TLineInfo): PNode = # returns a[].b as a node - result = indirectAccess(a, b.id, info) + result = indirectAccess(a, b.itemId, info) proc indirectAccess*(a, b: PSym, info: TLineInfo): PNode = result = indirectAccess(newSymNode(a), b, info) -proc genAddrOf*(n: PNode): PNode = +proc genAddrOf*(n: PNode; idgen: IdGenerator; typeKind = tyPtr): PNode = result = newNodeI(nkAddr, n.info, 1) result[0] = n - result.typ = newType(tyPtr, n.typ.owner) + result.typ = newType(typeKind, idgen, n.typ.owner) result.typ.rawAddSon(n.typ) proc genDeref*(n: PNode; k = nkHiddenDeref): PNode = result = newNodeIT(k, n.info, - n.typ.skipTypes(abstractInst)[0]) + n.typ.skipTypes(abstractInst).elementType) result.add n proc callCodegenProc*(g: ModuleGraph; name: string; info: TLineInfo = unknownLineInfo; - arg1, arg2, arg3, optionalArgs: PNode = nil): PNode = + arg1: PNode = nil, arg2: PNode = nil, + arg3: PNode = nil, optionalArgs: PNode = nil): PNode = result = newNodeI(nkCall, info) let sym = magicsys.getCompilerProc(g, name) if sym == nil: @@ -337,7 +344,7 @@ proc callCodegenProc*(g: ModuleGraph; name: string; if optionalArgs != nil: for i in 1..<optionalArgs.len-2: result.add optionalArgs[i] - result.typ = sym.typ[0] + result.typ = sym.typ.returnType proc newIntLit*(g: ModuleGraph; info: TLineInfo; value: BiggestInt): PNode = result = nkIntLit.newIntNode(value) @@ -361,14 +368,3 @@ proc genLen*(g: ModuleGraph; n: PNode): PNode = result[0] = newSymNode(getSysMagic(g, n.info, "len", mLengthSeq)) result[1] = n -proc hoistExpr*(varSection, expr: PNode, name: PIdent, owner: PSym): PSym = - result = newSym(skLet, name, owner, varSection.info, owner.options) - result.flags.incl sfHoisted - result.typ = expr.typ - - var varDef = newNodeI(nkIdentDefs, varSection.info, 3) - varDef[0] = newSymNode(result) - varDef[1] = newNodeI(nkEmpty, varSection.info) - varDef[2] = expr - - varSection.add varDef |