diff options
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/aliases.nim | 2 | ||||
-rwxr-xr-x | compiler/astalgo.nim | 4 | ||||
-rw-r--r-- | compiler/ccgcalls.nim | 92 | ||||
-rwxr-xr-x | compiler/ccgexprs.nim | 5 | ||||
-rwxr-xr-x | compiler/ccgstmts.nim | 26 | ||||
-rwxr-xr-x | compiler/cgen.nim | 29 | ||||
-rwxr-xr-x | compiler/pragmas.nim | 2 | ||||
-rwxr-xr-x | compiler/semexprs.nim | 6 | ||||
-rw-r--r-- | compiler/semmagic.nim | 4 |
9 files changed, 104 insertions, 66 deletions
diff --git a/compiler/aliases.nim b/compiler/aliases.nim index e5f58356e..aa579feee 100644 --- a/compiler/aliases.nim +++ b/compiler/aliases.nim @@ -41,7 +41,7 @@ proc isPartOfAux(n: PNode, b: PType, marker: var TIntSet): TAnalysisResult = proc isPartOfAux(a, b: PType, marker: var TIntSet): TAnalysisResult = result = arNo - if a == nil: return + if a == nil or b == nil: return if ContainsOrIncl(marker, a.id): return if compareTypes(a, b, dcEqIgnoreDistinct): return arYes case a.kind diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim index d405bd34c..94046a723 100755 --- a/compiler/astalgo.nim +++ b/compiler/astalgo.nim @@ -155,9 +155,7 @@ proc SameValue*(a, b: PNode): bool = if b.kind in {nkFloatLit..nkFloat64Lit}: result = a.floatVal == b.floatVal of nkStrLit..nkTripleStrLit: if b.kind in {nkStrLit..nkTripleStrLit}: result = a.strVal == b.strVal - else: - debug a - debug b + else: InternalError(a.info, "SameValue") proc leValue*(a, b: PNode): bool = diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim index 1c57479ae..570c931fb 100644 --- a/compiler/ccgcalls.nim +++ b/compiler/ccgcalls.nim @@ -10,16 +10,30 @@ type TAfterCallActions = tuple[p: BProc, actions: PRope] -proc fixupCall(p: BProc, t: PNode, d: var TLoc, pl: PRope) = +proc leftAppearsOnRightSide(le, ri: PNode): bool = + if le != nil: + for i in 1 .. <ri.len: + if le.isPartOf(ri[i]) != arNo: return true + +proc hasNoInit(call: PNode): bool {.inline.} = + result = call.sons[0].kind == nkSym and sfNoInit in call.sons[0].sym.flags + +proc resetLoc(p: BProc, d: var TLoc) = + zeroVar(p, d, containsGarbageCollectedRef(d.t)) + +proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc, pl: PRope) = var pl = pl - var typ = t.sons[0].typ # getUniqueType() is too expensive here! + var typ = ri.sons[0].typ # getUniqueType() is too expensive here! if typ.sons[0] != nil: if isInvalidReturnType(typ.sons[0]): - if sonsLen(t) > 1: app(pl, ", ") - # beware of 'result = p(result)'. We always allocate a temporary: - if d.k in {locTemp, locNone}: - # We already got a temp. Great, special case it: + if sonsLen(ri) > 1: app(pl, ", ") + # beware of 'result = p(result)'. We may need to allocate a temporary: + if d.k in {locTemp, locNone} or not leftAppearsOnRightSide(le, ri): + # Great, we can use 'd': if d.k == locNone: getTemp(p, typ.sons[0], d) + elif d.k notin {locExpr, locTemp} and not hasNoInit(ri): + # reset before pass as 'result' var: + resetLoc(p, d) app(pl, addrLoc(d)) app(pl, ")") app(p.s[cpsStmts], pl) @@ -117,40 +131,40 @@ proc genArgNoParam(aca: var TAfterCallActions, n: PNode): PRope = initLocExpr(aca.p, n, a) result = rdLoc(a) -proc genCall(p: BProc, t: PNode, d: var TLoc) = +proc genPrefixCall(p: BProc, le, ri: PNode, d: var TLoc) = var op: TLoc var aca: TAfterCallActions aca.p = p # this is a hotspot in the compiler - initLocExpr(p, t.sons[0], op) + initLocExpr(p, ri.sons[0], op) var pl = con(op.r, "(") - var typ = t.sons[0].typ # getUniqueType() is too expensive here! + var typ = ri.sons[0].typ # getUniqueType() is too expensive here! assert(typ.kind == tyProc) - var length = sonsLen(t) + var length = sonsLen(ri) for i in countup(1, length - 1): assert(sonsLen(typ) == sonsLen(typ.n)) if i < sonsLen(typ): assert(typ.n.sons[i].kind == nkSym) - app(pl, genArg(aca, t.sons[i], typ.n.sons[i].sym)) + app(pl, genArg(aca, ri.sons[i], typ.n.sons[i].sym)) else: - app(pl, genArgNoParam(aca, t.sons[i])) + app(pl, genArgNoParam(aca, ri.sons[i])) if i < length - 1: app(pl, ", ") - fixupCall(p, t, d, pl) + fixupCall(p, le, ri, d, pl) emitAfterCallActions(aca) -proc genInfixCall(p: BProc, t: PNode, d: var TLoc) = +proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) = var op, a: TLoc var aca: TAfterCallActions aca.p = p - initLocExpr(p, t.sons[0], op) + initLocExpr(p, ri.sons[0], op) var pl: PRope = nil - var typ = t.sons[0].typ # getUniqueType() is too expensive here! + var typ = ri.sons[0].typ # getUniqueType() is too expensive here! assert(typ.kind == tyProc) - var length = sonsLen(t) + var length = sonsLen(ri) assert(sonsLen(typ) == sonsLen(typ.n)) var param = typ.n.sons[1].sym - app(pl, genArg(aca, t.sons[1], param)) + app(pl, genArg(aca, ri.sons[1], param)) if skipTypes(param.typ, {tyGenericInst}).kind == tyPtr: app(pl, "->") else: app(pl, ".") @@ -160,45 +174,45 @@ proc genInfixCall(p: BProc, t: PNode, d: var TLoc) = assert(sonsLen(typ) == sonsLen(typ.n)) if i < sonsLen(typ): assert(typ.n.sons[i].kind == nkSym) - app(pl, genArg(aca, t.sons[i], typ.n.sons[i].sym)) + app(pl, genArg(aca, ri.sons[i], typ.n.sons[i].sym)) else: - app(pl, genArgNoParam(aca, t.sons[i])) + app(pl, genArgNoParam(aca, ri.sons[i])) if i < length - 1: app(pl, ", ") - fixupCall(p, t, d, pl) + fixupCall(p, le, ri, d, pl) emitAfterCallActions(aca) -proc genNamedParamCall(p: BProc, t: PNode, d: var TLoc) = +proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) = # generates a crappy ObjC call var op, a: TLoc var aca: TAfterCallActions aca.p = p - initLocExpr(p, t.sons[0], op) + initLocExpr(p, ri.sons[0], op) var pl = toRope"[" - var typ = t.sons[0].typ # getUniqueType() is too expensive here! + var typ = ri.sons[0].typ # getUniqueType() is too expensive here! assert(typ.kind == tyProc) - var length = sonsLen(t) + var length = sonsLen(ri) assert(sonsLen(typ) == sonsLen(typ.n)) if length > 1: - app(pl, genArg(aca, t.sons[1], typ.n.sons[1].sym)) + app(pl, genArg(aca, ri.sons[1], typ.n.sons[1].sym)) app(pl, " ") app(pl, op.r) if length > 2: app(pl, ": ") - app(pl, genArg(aca, t.sons[2], typ.n.sons[2].sym)) + app(pl, genArg(aca, ri.sons[2], typ.n.sons[2].sym)) for i in countup(3, length-1): assert(sonsLen(typ) == sonsLen(typ.n)) if i >= sonsLen(typ): - InternalError(t.info, "varargs for objective C method?") + InternalError(ri.info, "varargs for objective C method?") assert(typ.n.sons[i].kind == nkSym) var param = typ.n.sons[i].sym app(pl, " ") app(pl, param.name.s) app(pl, ": ") - app(pl, genArg(aca, t.sons[i], param)) + app(pl, genArg(aca, ri.sons[i], param)) if typ.sons[0] != nil: if isInvalidReturnType(typ.sons[0]): - if sonsLen(t) > 1: app(pl, " ") + if sonsLen(ri) > 1: app(pl, " ") # beware of 'result = p(result)'. We always allocate a temporary: if d.k in {locTemp, locNone}: # We already got a temp. Great, special case it: @@ -230,3 +244,21 @@ proc genNamedParamCall(p: BProc, t: PNode, d: var TLoc) = appf(p.s[cpsStmts], ";$n") emitAfterCallActions(aca) +proc genCall(p: BProc, e: PNode, d: var TLoc) = + if e.sons[0].kind == nkSym and sfInfixCall in e.sons[0].sym.flags and + e.len >= 2: + genInfixCall(p, nil, e, d) + elif e.sons[0].kind == nkSym and sfNamedParamCall in e.sons[0].sym.flags: + genNamedParamCall(p, e, d) + else: + genPrefixCall(p, nil, e, d) + +proc genAsgnCall(p: BProc, le, ri: PNode, d: var TLoc) = + if ri.sons[0].kind == nkSym and sfInfixCall in ri.sons[0].sym.flags and + ri.len >= 2: + genInfixCall(p, le, ri, d) + elif ri.sons[0].kind == nkSym and sfNamedParamCall in ri.sons[0].sym.flags: + genNamedParamCall(p, ri, d) + else: + genPrefixCall(p, le, ri, d) + diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 3a2c5965b..ddd272fba 100755 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -1628,11 +1628,6 @@ proc expr(p: BProc, e: PNode, d: var TLoc) = nkCallStrLit: if e.sons[0].kind == nkSym and e.sons[0].sym.magic != mNone: genMagicExpr(p, e, d, e.sons[0].sym.magic) - elif e.sons[0].kind == nkSym and sfInfixCall in e.sons[0].sym.flags and - e.len >= 2: - genInfixCall(p, e, d) - elif e.sons[0].kind == nkSym and sfNamedParamCall in e.sons[0].sym.flags: - genNamedParamCall(p, e, d) else: genCall(p, e, d) of nkCurly: diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index a994f27f3..108d7f071 100755 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -18,16 +18,16 @@ proc genVarTuple(p: BProc, n: PNode) = if n.kind != nkVarTuple: InternalError(n.info, "genVarTuple") var L = sonsLen(n) genLineDir(p, n) - initLocExpr(p, n.sons[L - 1], tup) + initLocExpr(p, n.sons[L-1], tup) var t = tup.t - for i in countup(0, L - 3): + for i in countup(0, L-3): var v = n.sons[i].sym if sfGlobal in v.flags: assignGlobalVar(p, v) genObjectInit(p, cpsInit, v.typ, v.loc, true) - else: + else: assignLocalVar(p, v) - initVariable(p, v) + initLocalVar(p, v, immediateAsgn=true) initLoc(field, locExpr, t.sons[i], tup.s) if t.n == nil: field.r = ropef("$1.Field$2", [rdLoc(tup), toRope(i)]) @@ -37,17 +37,25 @@ proc genVarTuple(p: BProc, n: PNode) = [rdLoc(tup), mangleRecFieldName(t.n.sons[i].sym, t)]) putLocIntoDest(p, v.loc, field) +proc loadInto(p: BProc, le, ri: PNode, a: var TLoc) {.inline.} = + if ri.kind in nkCallKinds and (ri.sons[0].kind != nkSym or + ri.sons[0].sym.magic == mNone): + genAsgnCall(p, le, ri, a) + else: + expr(p, ri, a) + proc genSingleVar(p: BProc, a: PNode) = var v = a.sons[0].sym + var immediateAsgn = a.sons[2].kind != nkEmpty if sfGlobal in v.flags: assignGlobalVar(p, v) genObjectInit(p, cpsInit, v.typ, v.loc, true) - else: + else: assignLocalVar(p, v) - initVariable(p, v) - if a.sons[2].kind != nkEmpty: + initLocalVar(p, v, immediateAsgn) + if immediateAsgn: genLineDir(p, a) - expr(p, a.sons[2], v.loc) + loadInto(p, a.sons[0], a.sons[2], v.loc) proc genVarStmt(p: BProc, n: PNode) = for i in countup(0, sonsLen(n) - 1): @@ -658,7 +666,7 @@ proc genAsgn(p: BProc, e: PNode, fastAsgn: bool) = InitLocExpr(p, e.sons[0], a) if fastAsgn: incl(a.flags, lfNoDeepCopy) assert(a.t != nil) - expr(p, e.sons[1], a) + loadInto(p, e.sons[0], e.sons[1], a) else: asgnFieldDiscriminant(p, e) diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 2018d7e6d..aa07f40aa 100755 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -14,7 +14,7 @@ import options, intsets, nversion, nimsets, msgs, crc, bitsets, idents, lists, types, ccgutils, os, times, ropes, math, passes, rodread, wordrecg, treetab, cgmeth, - rodutils, renderer, idgen, cgendata, ccgmerge, semfold + rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases when options.hasTinyCBackend: import tccgen @@ -235,16 +235,17 @@ proc zeroVar(p: BProc, loc: TLoc, containsGCref: bool) = genRefAssign(p, loc, nilLoc, {afSrcIsNil}) else: appf(p.s[cpsStmts], "$1 = 0;$n", [rdLoc(loc)]) - else: + else: if containsGcref and p.WithInLoop > 0: appf(p.s[cpsInit], "memset((void*)$1, 0, sizeof($2));$n", [addrLoc(loc), rdLoc(loc)]) + genObjectInit(p, cpsInit, loc.t, loc, true) appcg(p, cpsStmts, "#genericReset((void*)$1, $2);$n", [addrLoc(loc), genTypeInfo(p.module, loc.t)]) else: appf(p.s[cpsStmts], "memset((void*)$1, 0, sizeof($2));$n", [addrLoc(loc), rdLoc(loc)]) - genObjectInit(p, cpsInit, loc.t, loc, true) + genObjectInit(p, cpsStmts, loc.t, loc, true) proc zeroTemp(p: BProc, loc: TLoc) = if skipTypes(loc.t, abstractVarRange).Kind notin @@ -259,15 +260,22 @@ proc zeroTemp(p: BProc, loc: TLoc) = else: appf(p.s[cpsStmts], "memset((void*)$1, 0, sizeof($2));$n", [addrLoc(loc), rdLoc(loc)]) + # XXX no object init necessary for temporaries? when false: appcg(p, cpsStmts, "#genericReset((void*)$1, $2);$n", [addrLoc(loc), genTypeInfo(p.module, loc.t)]) -proc initVariable(p: BProc, v: PSym) = +proc initLocalVar(p: BProc, v: PSym, immediateAsgn: bool) = if sfNoInit notin v.flags: - var b = containsGarbageCollectedRef(v.typ) - if b or v.ast == nil: - zeroVar(p, v.loc, b) + # we know it is a local variable and thus on the stack! + # If ``not immediateAsgn`` it is not initialized in a binding like + # ``var v = X`` and thus we need to init it. + # If ``v`` contains a GC-ref we may pass it to ``unsureAsgnRef`` somehow + # which requires initialization. However this can really only happen if + # ``var v = X()`` gets transformed into ``X(&v)``. + # Nowadays the logic in ccgcalls deals with this case however. + if not immediateAsgn: + zeroVar(p, v.loc, containsGarbageCollectedRef(v.typ)) proc initTemp(p: BProc, tmp: var TLoc) = if containsGarbageCollectedRef(tmp.t) or isInvalidReturnType(tmp.t): @@ -534,13 +542,14 @@ proc genProcAux(m: BModule, prc: PSym) = assert(prc.ast != nil) if sfPure notin prc.flags and prc.typ.sons[0] != nil: var res = prc.ast.sons[resultPos].sym # get result symbol - if not isInvalidReturnType(prc.typ.sons[0]): + if not isInvalidReturnType(prc.typ.sons[0]): + if sfNoInit in prc.flags: incl(res.flags, sfNoInit) # declare the result symbol: assignLocalVar(p, res) assert(res.loc.r != nil) returnStmt = ropeff("return $1;$n", "ret $1$n", [rdLoc(res.loc)]) - initVariable(p, res) - else: + initLocalVar(p, res, immediateAsgn=false) + else: fillResult(res) assignParam(p, res) if skipTypes(res.typ, abstractInst).kind == tyArray: diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index d4ea3226d..a291d4741 100755 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -23,7 +23,7 @@ const wMagic, wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader, wCompilerProc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge, wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC, - wNoStackFrame, wError, wDiscardable} + wNoStackFrame, wError, wDiscardable, wNoInit} converterPragmas* = procPragmas methodPragmas* = procPragmas macroPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index a08e9c875..a5093f567 100755 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -983,12 +983,6 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode = else: result = semDirectOp(c, n, flags) of mExpandToAst: result = semExpandToAst(c, n, s, flags) - of mAstToStr: - if sonsLen(n) == 2: - result = newStrNodeT(renderTree(n[1], {renderNoComments}), n) - result.typ = getSysType(tyString) - else: - result = semDirectOp(c, n, flags) else: result = semDirectOp(c, n, flags) proc semIfExpr(c: PContext, n: PNode): PNode = diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index da1101729..696988fd3 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -31,6 +31,8 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode, case n[0].sym.magic of mSlurp: result = semSlurp(c, n, flags) of mIsPartOf: result = semIsPartOf(c, n, flags) + of mAstToStr: + result = newStrNodeT(renderTree(n[1], {renderNoComments}), n) + result.typ = getSysType(tyString) else: result = n - |