diff options
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/ast.nim | 3 | ||||
-rw-r--r-- | compiler/astalgo.nim | 6 | ||||
-rw-r--r-- | compiler/ccgexprs.nim | 12 | ||||
-rw-r--r-- | compiler/ccgstmts.nim | 3 | ||||
-rw-r--r-- | compiler/cgen.nim | 2 | ||||
-rw-r--r-- | compiler/cgmeth.nim | 6 | ||||
-rw-r--r-- | compiler/destroyer.nim | 177 | ||||
-rw-r--r-- | compiler/dfa.nim | 2 | ||||
-rw-r--r-- | compiler/extccomp.nim | 34 | ||||
-rw-r--r-- | compiler/jsgen.nim | 2 | ||||
-rw-r--r-- | compiler/modulegraphs.nim | 2 | ||||
-rw-r--r-- | compiler/nim.nim | 8 | ||||
-rw-r--r-- | compiler/semdata.nim | 6 | ||||
-rw-r--r-- | compiler/semfold.nim | 16 | ||||
-rw-r--r-- | compiler/semmagic.nim | 2 | ||||
-rw-r--r-- | compiler/semtypes.nim | 4 |
16 files changed, 196 insertions, 89 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index 0247acb03..5f5f296cb 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -723,10 +723,9 @@ type sons*: TNodeSeq comment*: string - TSymSeq* = seq[PSym] TStrTable* = object # a table[PIdent] of PSym counter*: int - data*: TSymSeq + data*: seq[PSym] # -------------- backend information ------------------------------- TLocKind* = enum diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim index b2671d81e..60eecbdc5 100644 --- a/compiler/astalgo.nim +++ b/compiler/astalgo.nim @@ -507,7 +507,7 @@ proc strTableContains*(t: TStrTable, n: PSym): bool = h = nextTry(h, high(t.data)) result = false -proc strTableRawInsert(data: var TSymSeq, n: PSym) = +proc strTableRawInsert(data: var seq[PSym], n: PSym) = var h: Hash = n.name.h and high(data) if sfImmediate notin n.flags: # fast path: @@ -535,7 +535,7 @@ proc strTableRawInsert(data: var TSymSeq, n: PSym) = data[h] = n if favPos >= 0: swap data[h], data[favPos] -proc symTabReplaceRaw(data: var TSymSeq, prevSym: PSym, newSym: PSym) = +proc symTabReplaceRaw(data: var seq[PSym], prevSym: PSym, newSym: PSym) = assert prevSym.name.h == newSym.name.h var h: Hash = prevSym.name.h and high(data) while data[h] != nil: @@ -549,7 +549,7 @@ proc symTabReplace*(t: var TStrTable, prevSym: PSym, newSym: PSym) = symTabReplaceRaw(t.data, prevSym, newSym) proc strTableEnlarge(t: var TStrTable) = - var n: TSymSeq + var n: seq[PSym] newSeq(n, len(t.data) * GrowthFactor) for i in countup(0, high(t.data)): if t.data[i] != nil: strTableRawInsert(n, t.data[i]) diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index cab2c78f5..d00371dd8 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -866,15 +866,15 @@ proc genArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) = # semantic pass has already checked for const index expressions if firstOrd(p.config, ty) == 0: if (firstOrd(p.config, b.t) < firstOrd(p.config, ty)) or (lastOrd(p.config, b.t) > lastOrd(p.config, ty)): - linefmt(p, cpsStmts, "if ((NU)($1) > (NU)($2)) #raiseIndexError();$n", + linefmt(p, cpsStmts, "if ((NU)($1) > (NU)($2)) #raiseIndexError2($1, $2);$n", rdCharLoc(b), intLiteral(lastOrd(p.config, ty))) else: - linefmt(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseIndexError();$n", + linefmt(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseIndexError3($1, $2, $3);$n", rdCharLoc(b), first, intLiteral(lastOrd(p.config, ty))) else: let idx = getOrdValue(y) if idx < firstOrd(p.config, ty) or idx > lastOrd(p.config, ty): - localError(p.config, x.info, "index out of bounds") + localError(p.config, x.info, formatErrorIndexBound(idx, firstOrd(p.config, ty), lastOrd(p.config, ty))) d.inheritLocation(a) putIntoDest(p, d, n, ropecg(p.module, "$1[($2)- $3]", rdLoc(a), rdCharLoc(b), first), a.storage) @@ -913,7 +913,7 @@ proc genOpenArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) = initLocExpr(p, x, a) initLocExpr(p, y, b) # emit range check: if optBoundsCheck in p.options: - linefmt(p, cpsStmts, "if ((NU)($1) >= (NU)($2Len_0)) #raiseIndexError();$n", + linefmt(p, cpsStmts, "if ((NU)($1) >= (NU)($2Len_0)) #raiseIndexError2($1,$2Len_0-1);$n", rdLoc(b), rdLoc(a)) # BUGFIX: ``>=`` and not ``>``! inheritLocation(d, a) putIntoDest(p, d, n, @@ -929,11 +929,11 @@ proc genSeqElem(p: BProc, n, x, y: PNode, d: var TLoc) = if optBoundsCheck in p.options: if ty.kind == tyString and (not defined(nimNoZeroTerminator) or optLaxStrings in p.options): linefmt(p, cpsStmts, - "if ((NU)($1) > (NU)$2) #raiseIndexError();$n", + "if ((NU)($1) > (NU)$2) #raiseIndexError2($1,$2);$n", rdLoc(b), lenExpr(p, a)) else: linefmt(p, cpsStmts, - "if ((NU)($1) >= (NU)$2) #raiseIndexError();$n", + "if ((NU)($1) >= (NU)$2) #raiseIndexError2($1,$2-1);$n", rdLoc(b), lenExpr(p, a)) if d.k == locNone: d.storage = OnHeap if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}: diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index e83b80b7c..6c33b302d 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -559,7 +559,8 @@ proc genParForStmt(p: BProc, t: PNode) = initLocExpr(p, call.sons[1], rangeA) initLocExpr(p, call.sons[2], rangeB) - lineF(p, cpsStmts, "#pragma omp $4$n" & + # $n at the beginning because of #9710 + lineF(p, cpsStmts, "$n#pragma omp $4$n" & "for ($1 = $2; $1 <= $3; ++$1)", [forLoopVar.loc.rdLoc, rangeA.rdLoc, rangeB.rdLoc, diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 3545edc88..457a6e176 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -16,6 +16,8 @@ import condsyms, rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases, lowerings, tables, sets, ndi, lineinfos, pathutils, transf +import system/helpers2 + when not defined(leanCompiler): import semparallel diff --git a/compiler/cgmeth.nim b/compiler/cgmeth.nim index cba07446f..f5014fa8c 100644 --- a/compiler/cgmeth.nim +++ b/compiler/cgmeth.nim @@ -188,7 +188,7 @@ proc methodDef*(g: ModuleGraph; s: PSym, fromCache: bool) = elif sfBase notin s.flags: message(g.config, s.info, warnUseBase) -proc relevantCol(methods: TSymSeq, col: int): bool = +proc relevantCol(methods: seq[PSym], col: int): bool = # returns true iff the position is relevant var t = methods[0].typ.sons[col].skipTypes(skipPtrs) if t.kind == tyObject: @@ -206,7 +206,7 @@ proc cmpSignatures(a, b: PSym, relevantCols: IntSet): int = if (d != high(int)) and d != 0: return d -proc sortBucket(a: var TSymSeq, relevantCols: IntSet) = +proc sortBucket(a: var seq[PSym], relevantCols: IntSet) = # we use shellsort here; fast and simple var n = len(a) var h = 1 @@ -225,7 +225,7 @@ proc sortBucket(a: var TSymSeq, relevantCols: IntSet) = a[j] = v if h == 1: break -proc genDispatcher(g: ModuleGraph; methods: TSymSeq, relevantCols: IntSet): PSym = +proc genDispatcher(g: ModuleGraph; methods: seq[PSym], relevantCols: IntSet): PSym = var base = lastSon(methods[0].ast).sym result = base var paramLen = sonsLen(base.typ) diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim index 51ad26f2c..40af11e70 100644 --- a/compiler/destroyer.nim +++ b/compiler/destroyer.nim @@ -116,7 +116,7 @@ Remarks: Rule 1.2 is not yet implemented because ``sink`` is currently import intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees, - strutils, options, dfa, lowerings, tables, modulegraphs, + strutils, options, dfa, lowerings, tables, modulegraphs, msgs, lineinfos, parampatterns const @@ -127,20 +127,11 @@ type owner: PSym g: ControlFlowGraph jumpTargets: IntSet - tmpObj: PType - tmp: PSym destroys, topLevelVars: PNode - toDropBit: Table[int, PSym] graph: ModuleGraph emptyNode: PNode otherRead: PNode -proc getTemp(c: var Con; typ: PType; info: TLineInfo): PNode = - # XXX why are temps fields in an object here? - let f = newSym(skField, getIdent(c.graph.cache, ":d" & $c.tmpObj.n.len), c.owner, info) - f.typ = typ - rawAddField c.tmpObj, f - result = rawDirectAccess(c.tmp, f) proc isHarmlessVar*(s: PSym; c: Con): bool = # 's' is harmless if it used only once and its @@ -329,22 +320,11 @@ proc genDestroy(c: Con; t: PType; dest: PNode): PNode = proc addTopVar(c: var Con; v: PNode) = c.topLevelVars.add newTree(nkIdentDefs, v, c.emptyNode, c.emptyNode) -proc dropBit(c: var Con; s: PSym): PSym = - result = c.toDropBit.getOrDefault(s.id) - assert result != nil - -proc registerDropBit(c: var Con; s: PSym) = - let result = newSym(skTemp, getIdent(c.graph.cache, s.name.s & "_AliveBit"), c.owner, s.info) - result.typ = getSysType(c.graph, s.info, tyBool) - let trueVal = newIntTypeNode(nkIntLit, 1, result.typ) - c.topLevelVars.add newTree(nkIdentDefs, newSymNode result, c.emptyNode, trueVal) - c.toDropBit[s.id] = result - # generate: - # if not sinkParam_AliveBit: `=destroy`(sinkParam) - let t = s.typ.skipTypes({tyGenericInst, tyAlias, tySink}) - if t.destructor != nil: - c.destroys.add newTree(nkIfStmt, - newTree(nkElifBranch, newSymNode result, genDestroy(c, t, newSymNode s))) +proc getTemp(c: var Con; typ: PType; info: TLineInfo): PNode = + let sym = newSym(skTemp, getIdent(c.graph.cache, ":tmpD"), c.owner, info) + sym.typ = typ + result = newSymNode(sym) + c.addTopVar(result) proc p(n: PNode; c: var Con): PNode @@ -355,16 +335,6 @@ template recurse(n, dest) = proc isSinkParam(s: PSym): bool {.inline.} = result = s.kind == skParam and s.typ.kind == tySink -proc destructiveMoveSink(n: PNode; c: var Con): PNode = - # generate: (chckMove(sinkParam_AliveBit); sinkParam_AliveBit = false; sinkParam) - result = newNodeIT(nkStmtListExpr, n.info, n.typ) - let bit = newSymNode dropBit(c, n.sym) - if optMoveCheck in c.owner.options: - result.add callCodegenProc(c.graph, "chckMove", bit.info, bit) - result.add newTree(nkAsgn, bit, - newIntTypeNode(nkIntLit, 0, getSysType(c.graph, n.info, tyBool))) - result.add n - proc genMagicCall(n: PNode; c: var Con; magicname: string; m: TMagic): PNode = result = newNodeI(nkCall, n.info) result.add(newSymNode(createMagic(c.graph, magicname, m))) @@ -395,6 +365,12 @@ proc destructiveMoveVar(n: PNode; c: var Con): PNode = result.add genWasMoved(n, c) result.add tempAsNode +proc sinkParamIsLastReadCheck(c: var Con, s: PNode) = + assert s.kind == nkSym and s.sym.kind == skParam + if not isLastRead(s, c): + localError(c.graph.config, c.otherRead.info, "sink parameter `" & $s.sym.name.s & + "` is already consumed at " & toFileLineCol(c. graph.config, s.info)) + proc passCopyToSink(n: PNode; c: var Con): PNode = result = newNodeIT(nkStmtListExpr, n.info, n.typ) let tmp = getTemp(c, n.typ, n.info) @@ -411,6 +387,11 @@ proc passCopyToSink(n: PNode; c: var Con): PNode = result.add tmp proc pArg(arg: PNode; c: var Con; isSink: bool): PNode = + template pArgIfTyped(arg_part: PNode): PNode = + # typ is nil if we are in if/case expr branch with noreturn + if arg_part.typ == nil: p(arg_part, c) + else: pArg(arg_part, c, isSink) + if isSink: if arg.kind in nkCallKinds: # recurse but skip the call expression in order to prevent @@ -421,17 +402,53 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode = result.add arg[0] for i in 1..<arg.len: result.add pArg(arg[i], c, i < L and parameters[i].kind == tySink) - elif arg.kind in {nkObjConstr, nkCharLit..nkFloat128Lit}: + elif arg.kind in {nkBracket, nkObjConstr, nkTupleConstr, nkBracket, nkCharLit..nkFloat128Lit}: discard "object construction to sink parameter: nothing to do" result = arg + elif arg.kind == nkSym and isSinkParam(arg.sym): + # Sinked params can be consumed only once. We need to reset the memory + # to disable the destructor which we have not elided + sinkParamIsLastReadCheck(c, arg) + result = destructiveMoveVar(arg, c) elif arg.kind == nkSym and arg.sym.kind in InterestingSyms and isLastRead(arg, c): - # if x is a variable and it its last read we eliminate its - # destructor invokation, but don't. We need to reset its memory - # to disable its destructor which we have not elided: + # it is the last read, can be sinked. We need to reset the memory + # to disable the destructor which we have not elided result = destructiveMoveVar(arg, c) - elif arg.kind == nkSym and isSinkParam(arg.sym): - # mark the sink parameter as used: - result = destructiveMoveSink(arg, c) + elif arg.kind in {nkBlockExpr, nkBlockStmt}: + result = copyNode(arg) + result.add arg[0] + result.add pArg(arg[1], c, isSink) + elif arg.kind == nkStmtListExpr: + result = copyNode(arg) + for i in 0..arg.len-2: + result.add p(arg[i], c) + result.add pArg(arg[^1], c, isSink) + elif arg.kind in {nkIfExpr, nkIfStmt}: + result = copyNode(arg) + for i in 0..<arg.len: + var branch = copyNode(arg[i]) + if arg[i].kind in {nkElifBranch, nkElifExpr}: + branch.add p(arg[i][0], c) + branch.add pArgIfTyped(arg[i][1]) + else: + branch.add pArgIfTyped(arg[i][0]) + result.add branch + elif arg.kind == nkCaseStmt: + result = copyNode(arg) + result.add p(arg[0], c) + for i in 1..<arg.len: + var branch: PNode + if arg[i].kind == nkOfbranch: + branch = arg[i] # of branch conditions are constants + branch[^1] = pArgIfTyped(arg[i][^1]) + elif arg[i].kind in {nkElifBranch, nkElifExpr}: + branch = copyNode(arg[i]) + branch.add p(arg[i][0], c) + branch.add pArgIfTyped(arg[i][1]) + else: + branch = copyNode(arg[i]) + branch.add pArgIfTyped(arg[i][0]) + result.add branch else: # an object that is not temporary but passed to a 'sink' parameter # results in a copy. @@ -440,6 +457,11 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode = result = p(arg, c) proc moveOrCopy(dest, ri: PNode; c: var Con): PNode = + template moveOrCopyIfTyped(ri_part: PNode): PNode = + # typ is nil if we are in if/case expr branch with noreturn + if ri_part.typ == nil: p(ri_part, c) + else: moveOrCopy(dest, ri_part, c) + case ri.kind of nkCallKinds: result = genSink(c, dest.typ, dest, ri) @@ -454,7 +476,7 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode = result.add ri2 of nkBracketExpr: if ri[0].kind == nkSym and isUnpackedTuple(ri[0].sym): - # unpacking of tuple: move out the elements + # unpacking of tuple: move out the elements result = genSink(c, dest.typ, dest, ri) else: result = genCopy(c, dest.typ, dest, ri) @@ -464,6 +486,45 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode = for i in 0..ri.len-2: result.add p(ri[i], c) result.add moveOrCopy(dest, ri[^1], c) + of nkBlockExpr, nkBlockStmt: + result = newNodeI(nkBlockStmt, ri.info) + result.add ri[0] ## add label + result.add moveOrCopy(dest, ri[1], c) + of nkIfExpr, nkIfStmt: + result = newNodeI(nkIfStmt, ri.info) + for i in 0..<ri.len: + var branch = copyNode(ri[i]) + if ri[i].kind in {nkElifBranch, nkElifExpr}: + branch.add p(ri[i][0], c) + branch.add moveOrCopyIfTyped(ri[i][1]) + else: + branch.add moveOrCopyIfTyped(ri[i][0]) + result.add branch + of nkCaseStmt: + result = newNodeI(nkCaseStmt, ri.info) + result.add p(ri[0], c) + for i in 1..<ri.len: + var branch: PNode + if ri[i].kind == nkOfbranch: + branch = ri[i] # of branch conditions are constants + branch[^1] = moveOrCopyIfTyped(ri[i][^1]) + elif ri[i].kind in {nkElifBranch, nkElifExpr}: + branch = copyNode(ri[i]) + branch.add p(ri[i][0], c) + branch.add moveOrCopyIfTyped(ri[i][1]) + else: + branch = copyNode(ri[i]) + branch.add moveOrCopyIfTyped(ri[i][0]) + result.add branch + of nkBracket: + # array constructor + result = genSink(c, dest.typ, dest, ri) + let ri2 = copyTree(ri) + for i in 0..<ri.len: + # everything that is passed to an array constructor is consumed, + # so these all act like 'sink' parameters: + ri2[i] = pArg(ri[i], c, isSink = true) + result.add ri2 of nkObjConstr: result = genSink(c, dest.typ, dest, ri) let ri2 = copyTree(ri) @@ -484,14 +545,17 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode = ri2[i] = pArg(ri[i], c, isSink = true) result.add ri2 of nkSym: - if ri.sym.kind != skParam and isLastRead(ri, c): + if isSinkParam(ri.sym): # Rule 3: `=sink`(x, z); wasMoved(z) + sinkParamIsLastReadCheck(c, ri) var snk = genSink(c, dest.typ, dest, ri) - snk.add p(ri, c) + snk.add ri + result = newTree(nkStmtList, snk, genMagicCall(ri, c, "wasMoved", mWasMoved)) + elif ri.sym.kind != skParam and isLastRead(ri, c): + # Rule 3: `=sink`(x, z); wasMoved(z) + var snk = genSink(c, dest.typ, dest, ri) + snk.add ri result = newTree(nkStmtList, snk, genMagicCall(ri, c, "wasMoved", mWasMoved)) - elif isSinkParam(ri.sym): - result = genSink(c, dest.typ, dest, ri) - result.add destructiveMoveSink(ri, c) else: result = genCopy(c, dest.typ, dest, ri) result.add p(ri, c) @@ -512,14 +576,15 @@ proc p(n: PNode; c: var Con): PNode = if it.kind == nkVarTuple and hasDestructor(ri.typ): let x = lowerTupleUnpacking(c.graph, it, c.owner) result.add p(x, c) - elif it.kind == nkIdentDefs and hasDestructor(it[0].typ) and not isUnpackedTuple(it[0].sym): + elif it.kind == nkIdentDefs and hasDestructor(it[0].typ): for j in 0..L-2: let v = it[j] doAssert v.kind == nkSym # move the variable declaration to the top of the frame: c.addTopVar v # make sure it's destroyed at the end of the proc: - c.destroys.add genDestroy(c, v.typ, v) + if not isUnpackedTuple(it[0].sym): + c.destroys.add genDestroy(c, v.typ, v) if ri.kind != nkEmpty: let r = moveOrCopy(v, ri, c) result.add r @@ -566,12 +631,8 @@ proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode = echo "injecting into ", n var c: Con c.owner = owner - c.tmp = newSym(skTemp, getIdent(g.cache, ":d"), owner, n.info) - c.tmpObj = createObj(g, owner, n.info) - c.tmp.typ = c.tmpObj c.destroys = newNodeI(nkStmtList, n.info) c.topLevelVars = newNodeI(nkVarSection, n.info) - c.toDropBit = initTable[int, PSym]() c.graph = g c.emptyNode = newNodeI(nkEmpty, n.info) let cfg = constructCfg(owner, n) @@ -586,10 +647,10 @@ proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode = let params = owner.typ.n for i in 1 ..< params.len: let param = params[i].sym - if param.typ.kind == tySink: registerDropBit(c, param) + if param.typ.kind == tySink and hasDestructor(param.typ): + c.destroys.add genDestroy(c, param.typ.skipTypes({tyGenericInst, tyAlias, tySink}), params[i]) + let body = p(n, c) - if c.tmp.typ.n.len > 0: - c.addTopVar(newSymNode c.tmp) result = newNodeI(nkStmtList, n.info) if c.topLevelVars.len > 0: result.add c.topLevelVars diff --git a/compiler/dfa.nim b/compiler/dfa.nim index 415cc4ab3..cd32d95d5 100644 --- a/compiler/dfa.nim +++ b/compiler/dfa.nim @@ -272,7 +272,7 @@ proc genReturn(c: var Con; n: PNode) = c.code.add Instr(n: n, kind: goto, dest: high(int) - c.code.len) const - InterestingSyms = {skVar, skResult, skLet} + InterestingSyms = {skVar, skResult, skLet, skParam} proc genUse(c: var Con; n: PNode) = var n = n diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim index f3f74ece8..2fe151a1c 100644 --- a/compiler/extccomp.nim +++ b/compiler/extccomp.nim @@ -763,6 +763,32 @@ proc execCmdsInParallel(conf: ConfigRef; cmds: seq[string]; prettyCb: proc (idx: rawMessage(conf, errGenerated, "execution of an external program failed: '$1'" % cmds.join()) +proc linkViaResponseFile(conf: ConfigRef; cmd: string) = + # Extracting the linker.exe here is a bit hacky but the best solution + # given ``buildLib``'s design. + var i = 0 + var last = 0 + if cmd.len > 0 and cmd[0] == '"': + inc i + while i < cmd.len and cmd[i] != '"': inc i + last = i + inc i + else: + while i < cmd.len and cmd[i] != ' ': inc i + last = i + while i < cmd.len and cmd[i] == ' ': inc i + let linkerArgs = conf.projectName & "_" & "linkerArgs.txt" + let args = cmd.substr(i) + # GCC's response files don't support backslashes. Junk. + if conf.cCompiler == ccGcc: + writeFile(linkerArgs, args.replace('\\', '/')) + else: + writeFile(linkerArgs, args) + try: + execLinkCmd(conf, cmd.substr(0, last) & " @" & linkerArgs) + finally: + removeFile(linkerArgs) + proc callCCompiler*(conf: ConfigRef; projectfile: AbsoluteFile) = var linkCmd: string @@ -795,7 +821,13 @@ proc callCCompiler*(conf: ConfigRef; projectfile: AbsoluteFile) = linkCmd = getLinkCmd(conf, projectfile, objfiles) if optCompileOnly notin conf.globalOptions: - execLinkCmd(conf, linkCmd) + if defined(windows) and linkCmd.len > 8_000: + # Windows's command line limit is about 8K (don't laugh...) so C compilers on + # Windows support a feature where the command line can be passed via ``@linkcmd`` + # to them. + linkViaResponseFile(conf, linkCmd) + else: + execLinkCmd(conf, linkCmd) else: linkCmd = "" if optGenScript in conf.globalOptions: diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index a9813f5c5..4d22c4224 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -945,7 +945,7 @@ proc needsNoCopy(p: PProc; y: PNode): bool = else: return (mapType(y.typ) != etyBaseIndex and (skipTypes(y.typ, abstractInst).kind in - {tyRef, tyPtr, tyLent, tyVar, tyCString} + IntegralTypes)) + {tyRef, tyPtr, tyLent, tyVar, tyCString, tyProc} + IntegralTypes)) return true proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) = diff --git a/compiler/modulegraphs.nim b/compiler/modulegraphs.nim index d05b301ae..63fa597ff 100644 --- a/compiler/modulegraphs.nim +++ b/compiler/modulegraphs.nim @@ -47,7 +47,7 @@ type doStopCompile*: proc(): bool {.closure.} usageSym*: PSym # for nimsuggest owners*: seq[PSym] - methods*: seq[tuple[methods: TSymSeq, dispatcher: PSym]] # needs serialization! + methods*: seq[tuple[methods: seq[PSym], dispatcher: PSym]] # needs serialization! systemModule*: PSym sysTypes*: array[TTypeKind, PType] compilerprocs*: TStrTable diff --git a/compiler/nim.nim b/compiler/nim.nim index 1c4dbd3be..cbd9d6f39 100644 --- a/compiler/nim.nim +++ b/compiler/nim.nim @@ -9,14 +9,14 @@ when defined(gcc) and defined(windows): when defined(x86): - {.link: "icons/nim.res".} + {.link: "../icons/nim.res".} else: - {.link: "icons/nim_icon.o".} + {.link: "../icons/nim_icon.o".} when defined(amd64) and defined(windows) and defined(vcc): - {.link: "icons/nim-amd64-windows-vcc.res".} + {.link: "../icons/nim-amd64-windows-vcc.res".} when defined(i386) and defined(windows) and defined(vcc): - {.link: "icons/nim-i386-windows-vcc.res".} + {.link: "../icons/nim-i386-windows-vcc.res".} import commands, lexer, condsyms, options, msgs, nversion, nimconf, ropes, diff --git a/compiler/semdata.nim b/compiler/semdata.nim index bec4a59a4..735c6f6b1 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -100,8 +100,8 @@ type compilesContextId*: int # > 0 if we are in a ``compiles`` magic compilesContextIdGenerator*: int inGenericInst*: int # > 0 if we are instantiating a generic - converters*: TSymSeq # sequence of converters - patterns*: TSymSeq # sequence of pattern matchers + converters*: seq[PSym] + patterns*: seq[PSym] # sequence of pattern matchers optionStack*: seq[POptionEntry] symMapping*: TIdTable # every gensym'ed symbol needs to be mapped # to some new symbol in a generic instantiation @@ -239,7 +239,7 @@ proc newContext*(graph: ModuleGraph; module: PSym): PContext = result.typesWithOps = @[] result.features = graph.config.features -proc inclSym(sq: var TSymSeq, s: PSym) = +proc inclSym(sq: var seq[PSym], s: PSym) = var L = len(sq) for i in countup(0, L - 1): if sq[i].id == s.id: return diff --git a/compiler/semfold.nim b/compiler/semfold.nim index 5ec702257..9e7ed5cee 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -15,6 +15,8 @@ import nversion, platform, math, msgs, os, condsyms, idents, renderer, types, commands, magicsys, modulegraphs, strtabs, lineinfos +import system/helpers2 + proc newIntNodeT*(intVal: BiggestInt, n: PNode; g: ModuleGraph): PNode = case skipTypes(n.typ, abstractVarRange).kind of tyInt: @@ -489,11 +491,11 @@ proc foldArrayAccess(m: PSym, n: PNode; g: ModuleGraph): PNode = result = x.sons[int(idx)] if result.kind == nkExprColonExpr: result = result.sons[1] else: - localError(g.config, n.info, "index out of bounds: " & $n) + localError(g.config, n.info, formatErrorIndexBound(idx, sonsLen(x)+1) & $n) of nkBracket: idx = idx - firstOrd(g.config, x.typ) if idx >= 0 and idx < x.len: result = x.sons[int(idx)] - else: localError(g.config, n.info, "index out of bounds: " & $n) + else: localError(g.config, n.info, formatErrorIndexBound(idx, x.len+1) & $n) of nkStrLit..nkTripleStrLit: result = newNodeIT(nkCharLit, x.info, n.typ) if idx >= 0 and idx < len(x.strVal): @@ -501,7 +503,7 @@ proc foldArrayAccess(m: PSym, n: PNode; g: ModuleGraph): PNode = elif idx == len(x.strVal) and optLaxStrings in g.config.options: discard else: - localError(g.config, n.info, "index out of bounds: " & $n) + localError(g.config, n.info, formatErrorIndexBound(idx, len(x.strVal)-1) & $n) else: discard proc foldFieldAccess(m: PSym, n: PNode; g: ModuleGraph): PNode = @@ -626,6 +628,14 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode = # It doesn't matter if the argument is const or not for mLengthArray. # This fixes bug #544. result = newIntNodeT(lengthOrd(g.config, n.sons[1].typ), n, g) + of mSizeOf: + let size = getSize(g.config, n[1].typ) + if size >= 0: + result = newIntNode(nkIntLit, size) + result.info = n.info + result.typ = getSysType(g, n.info, tyInt) + else: + result = nil of mAstToStr: result = newStrNodeT(renderTree(n[1], {renderNoComments}), n, g) of mConStrStr: diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index df2c084a1..7e61854b8 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -321,8 +321,6 @@ proc semOf(c: PContext, n: PNode): PNode = proc magicsAfterOverloadResolution(c: PContext, n: PNode, flags: TExprFlags): PNode = ## This is the preferred code point to implement magics. - ## This function basically works like a macro, with the difference - ## that it is implemented in the compiler and not on the nimvm. ## ``c`` the current module, a symbol table to a very good approximation ## ``n`` the ast like it would be passed to a real macro ## ``flags`` Some flags for more contextual information on how the diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 1e75b563e..f4ff97ba4 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -90,6 +90,8 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType = if sonsLen(v) == 2: strVal = v.sons[1] # second tuple part is the string value if skipTypes(strVal.typ, abstractInst).kind in {tyString, tyCString}: + if not isOrdinalType(v.sons[0].typ): + localError(c.config, v.sons[0].info, errOrdinalTypeExpected) x = getOrdValue(v.sons[0]) # first tuple part is the ordinal else: localError(c.config, strVal.info, errStringLiteralExpected) @@ -99,6 +101,8 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType = strVal = v x = counter else: + if not isOrdinalType(v.typ): + localError(c.config, v.info, errOrdinalTypeExpected) x = getOrdValue(v) if i != 1: if x != counter: incl(result.flags, tfEnumHasHoles) |