From e35c284422efe0f7cf137ed3713ebf83de85454c Mon Sep 17 00:00:00 2001 From: Timothee Cour Date: Tue, 3 Aug 2021 10:39:48 -0700 Subject: [PATCH 1/8] const works!! --- compiler/astalgo.nim | 6 ++ compiler/debugutils.nim | 2 + compiler/sem.nim | 2 + compiler/semstmts.nim | 21 +++++++ compiler/semtypes.nim | 2 + compiler/vm.nim | 3 + compiler/vmgen.nim | 7 ++- tests/misc/trfc_276.nim | 120 ++++++++++++++++++++++++++++++++++++++++ 8 files changed, 161 insertions(+), 2 deletions(-) create mode 100644 tests/misc/trfc_276.nim diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim index 94fa9da93298f..322cb050bab2c 100644 --- a/compiler/astalgo.nim +++ b/compiler/astalgo.nim @@ -527,6 +527,12 @@ proc value(this: var DebugPrinter; value: PSym) = this.value(value.name.s) this.key("id") this.value(value.id) + if value.owner != nil: + this.key "ownerName" + this.value($value.owner) # PRTEMP + # this.key "owner" + # this.value(value.owner) # PRTEMP + if value.kind in {skField, skEnumField, skParam}: this.key("position") this.value(value.position) diff --git a/compiler/debugutils.nim b/compiler/debugutils.nim index d109d2121ba69..7ed431feea224 100644 --- a/compiler/debugutils.nim +++ b/compiler/debugutils.nim @@ -54,3 +54,5 @@ proc isCompilerDebug*(): bool = {.undef(nimCompilerDebug).} echo 'x' conf0.isDefined("nimCompilerDebug") + +include timn/exp/nim_compiler_debugutils diff --git a/compiler/sem.nim b/compiler/sem.nim index 804325e564208..2b521c57a1d5d 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -214,6 +214,7 @@ proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym = proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym = # like newSymS, but considers gensym'ed symbols + dbgIf n, n.kind if n.kind == nkSym: # and sfGenSym in n.sym.flags: result = n.sym @@ -232,6 +233,7 @@ proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym = result.owner = getCurrOwner(c) else: result = newSym(kind, considerQuotedIdent(c, n), nextSymId c.idgen, getCurrOwner(c), n.info) + dbgIf result, result.owner, getCurrOwner(c) #if kind in {skForVar, skLet, skVar} and result.owner.kind == skModule: # incl(result.flags, sfGlobal) when defined(nimsuggest): diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index cc09291c5b2a6..53ac1c9e886d2 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -314,6 +314,7 @@ proc semIdentDef(c: PContext, n: PNode, kind: TSymKind): PSym = # echo "global variable here ", n.info, " ", result.name.s else: result = semIdentWithPragma(c, kind, n, {}) + dbgIf result.owner if result.owner.kind == skModule: incl(result.flags, sfGlobal) result.options = c.config.options @@ -525,6 +526,9 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = var def: PNode = c.graph.emptyNode if a[^1].kind != nkEmpty: def = semExprWithType(c, a[^1], {}) + if isCompilerDebug(): + dbg def, def.kind + debug2 def if def.kind in nkSymChoices and def[0].typ.skipTypes(abstractInst).kind == tyEnum: errorSymChoiceUseQualifier(c, def) @@ -590,13 +594,19 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = if a.kind != nkVarTuple: typ else: tup[j]) addToVarSection(c, result, n, a) continue + debugIf a[j] var v = semIdentDef(c, a[j], symkind) + dbgIf j, a.len, a[j], symkind, v, v.kind + dbgIf def, def.kind, v.owner, v.kind, v.flags, c.p.owner + debugIf v + styleCheckDef(c.config, v) onDef(a[j].info, v) if sfGenSym notin v.flags: if not isDiscardUnderscore(v): addInterfaceDecl(c, v) else: if v.owner == nil: v.owner = c.p.owner + dbgIf v.owner when oKeepVariableNames: if c.inUnrolledContext > 0: v.flags.incl(sfShadowed) else: @@ -672,8 +682,17 @@ proc semConst(c: PContext, n: PNode): PNode = var typFlags: TTypeAllowedFlags # don't evaluate here since the type compatibility check below may add a converter + let s2 = newSym(skLabel, c.cache.idAnon, nextSymId c.idgen, c.graph.owners[^1], n.info) + s2.flags.incl sfUsed + let ownerOld = c.p.owner + c.p.owner = s2 + dbgIf ownerOld, s2 + pushOwner(c, s2) + var def = semExprWithType(c, a[^1]) + + if def.kind == nkSym and def.sym.kind in {skTemplate, skMacro}: typFlags.incl taIsTemplateOrMacro elif def.typ.kind == tyTypeDesc and c.p.owner.kind != skMacro: @@ -731,6 +750,8 @@ proc semConst(c: PContext, n: PNode): PNode = else: def[j][1] b[j] = newSymNode(v) result.add b + c.p.owner = ownerOld + popOwner(c) dec c.inStaticContext include semfields diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index cb7f847a96034..2b006e07e9c41 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -487,6 +487,7 @@ proc semTuple(c: PContext, n: PNode, prev: PType): PType = proc semIdentVis(c: PContext, kind: TSymKind, n: PNode, allowed: TSymFlags): PSym = # identifier with visibility + dbgIf n, kind, allowed, n.kind if n.kind == nkPostfix: if n.len == 2: # for gensym'ed identifiers the identifier may already have been @@ -504,6 +505,7 @@ proc semIdentVis(c: PContext, kind: TSymKind, n: PNode, illFormedAst(n, c.config) else: result = newSymG(kind, n, c) + dbgIf result, result.owner proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode, allowed: TSymFlags): PSym = diff --git a/compiler/vm.nim b/compiler/vm.nim index 73a228b6c5bcb..b3abe6fb66dfc 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -2201,6 +2201,9 @@ proc evalConstExprAux(module: PSym; idgen: IdGenerator; var c = PCtx g.vm let oldMode = c.mode c.mode = mode + + # PRTEMP1 + let start = genExpr(c, n, requiresValue = mode!=emStaticStmt) if c.code[start].opcode == opcEof: return newNodeI(nkEmpty, n.info) assert c.code[start].opcode != opcEof diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 4957a3339fb45..aa123ec5f79c9 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -1495,11 +1495,14 @@ proc checkCanEval(c: PCtx; n: PNode) = if {sfCompileTime, sfGlobal} <= s.flags: return if s.importcCondVar: return if s.kind in {skVar, skTemp, skLet, skParam, skResult} and - not s.isOwnedBy(c.prc.sym) and s.owner != c.module and c.mode != emRepl: + not s.isOwnedBy(c.prc.sym) and s.owner != c.module and c.mode != emRepl and not (s.owner.kind == skLabel): # PRTEMP # little hack ahead for bug #12612: assume gensym'ed variables # are in the right scope: if sfGenSym in s.flags and c.prc.sym == nil: discard - else: cannotEval(c, n) + else: + dbg s, s.kind, s.isOwnedBy(c.prc.sym), s.owner, s.owner.kind, c.mode, c.prc.sym, s.flags + # , getCurrOwner(c) + cannotEval(c, n) elif s.kind in {skProc, skFunc, skConverter, skMethod, skIterator} and sfForward in s.flags: cannotEval(c, n) diff --git a/tests/misc/trfc_276.nim b/tests/misc/trfc_276.nim new file mode 100644 index 0000000000000..daf93521f6236 --- /dev/null +++ b/tests/misc/trfc_276.nim @@ -0,0 +1,120 @@ +# https://github.com/nim-lang/RFCs/issues/276 + +proc test1 = + const a = block: + let i = 2 + i + doAssert a == 2 +test1() + +static: # bug #10938 + for i in '1' .. '2': + var s: set[char] + doAssert s == {} + incl(s, i) + +block: + # this was causing issues in some variants + const SymChars: set[char] = {'a' .. 'b'} + var a = 'x' + discard contains(SymChars, a) + +static: + let i = 1 + var i2 = 2 + doAssert (i, i2) == (1, 2) + +proc test2() = + static: + let i = 1 + var i2 = 2 + doAssert (i, i2) == (1, 2) +test2() + +block: + type Foo = ref object + const + a: Foo = nil + +block: + type Fn = proc (a: cint) {.noconv.} # see CSighandlerT + const + foo = cast[Fn](0) + +block: # bug #13918 + const test = block: + var s = "" + for i in 1 .. 5: + var arr: array[3, int] + var val: int + s.add $arr & " " & $val + for j in 0 ..< len(arr): + arr[j] = i + val = i + s + doAssert test == "[0, 0, 0] 0[0, 0, 0] 0[0, 0, 0] 0[0, 0, 0] 0[0, 0, 0] 0" + +block: # bug #13312 + static: + for _ in 0 ..< 3: + var s: string + s.add("foo") + assert s == "foo" + +block: # bug #13887 + static: # https://github.com/nim-lang/Nim/issues/13887#issuecomment-655829572 + var x = 5 + var y = addr(x) + y[] += 10 + doAssert x == y[] + + block: # Example 1 + template fun() = + var s = @[10,11,12] + let z = s[0].addr + doAssert z[] == 10 + z[] = 100 + doAssert z[] == 100 + doAssert s[0] == 100 # was failing here + static: fun() # was failing here + fun() # was working + + block: # Example 2 + template fun() = + var s = @[10,11,12] + let a1 = cast[int](s[0].addr) # 4323682360 + let z = s[0].addr + let a2 = cast[int](z) # 10 => BUG + doAssert a1 == a2 + static: fun() # fails + + block: # Example 3 + template fun() = + var s = @[10.1,11.2,12.3] + let a1 = cast[int](s[0].addr) + let z = s[0].addr + let a2 = cast[int](z) + static: fun() + +block: # bug #12172 + const a = block: + var test: array[5, string] + test + proc test = + const a2 = block: + var test: array[5, string] # was error here + test + proc test2 = + const a3 = block: + let i = 0 # Error here too + i + +when false: + # xxx this doesn't work yet + block: + proc test = + const a = block: + template fn(x): untyped = + let i = 0 + i + fn(123) From a29f3b9ae5991b3343f055ddbf7eb0067c109437 Mon Sep 17 00:00:00 2001 From: Timothee Cour Date: Tue, 3 Aug 2021 10:45:33 -0700 Subject: [PATCH 2/8] cleanup --- compiler/sem.nim | 2 -- compiler/semstmts.nim | 14 -------------- compiler/semtypes.nim | 2 -- compiler/vmgen.nim | 3 +-- tests/misc/trfc_276.nim | 2 +- 5 files changed, 2 insertions(+), 21 deletions(-) diff --git a/compiler/sem.nim b/compiler/sem.nim index 2b521c57a1d5d..804325e564208 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -214,7 +214,6 @@ proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym = proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym = # like newSymS, but considers gensym'ed symbols - dbgIf n, n.kind if n.kind == nkSym: # and sfGenSym in n.sym.flags: result = n.sym @@ -233,7 +232,6 @@ proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym = result.owner = getCurrOwner(c) else: result = newSym(kind, considerQuotedIdent(c, n), nextSymId c.idgen, getCurrOwner(c), n.info) - dbgIf result, result.owner, getCurrOwner(c) #if kind in {skForVar, skLet, skVar} and result.owner.kind == skModule: # incl(result.flags, sfGlobal) when defined(nimsuggest): diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 53ac1c9e886d2..ea57c23041630 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -314,7 +314,6 @@ proc semIdentDef(c: PContext, n: PNode, kind: TSymKind): PSym = # echo "global variable here ", n.info, " ", result.name.s else: result = semIdentWithPragma(c, kind, n, {}) - dbgIf result.owner if result.owner.kind == skModule: incl(result.flags, sfGlobal) result.options = c.config.options @@ -526,9 +525,6 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = var def: PNode = c.graph.emptyNode if a[^1].kind != nkEmpty: def = semExprWithType(c, a[^1], {}) - if isCompilerDebug(): - dbg def, def.kind - debug2 def if def.kind in nkSymChoices and def[0].typ.skipTypes(abstractInst).kind == tyEnum: errorSymChoiceUseQualifier(c, def) @@ -594,19 +590,13 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = if a.kind != nkVarTuple: typ else: tup[j]) addToVarSection(c, result, n, a) continue - debugIf a[j] var v = semIdentDef(c, a[j], symkind) - dbgIf j, a.len, a[j], symkind, v, v.kind - dbgIf def, def.kind, v.owner, v.kind, v.flags, c.p.owner - debugIf v - styleCheckDef(c.config, v) onDef(a[j].info, v) if sfGenSym notin v.flags: if not isDiscardUnderscore(v): addInterfaceDecl(c, v) else: if v.owner == nil: v.owner = c.p.owner - dbgIf v.owner when oKeepVariableNames: if c.inUnrolledContext > 0: v.flags.incl(sfShadowed) else: @@ -686,13 +676,9 @@ proc semConst(c: PContext, n: PNode): PNode = s2.flags.incl sfUsed let ownerOld = c.p.owner c.p.owner = s2 - dbgIf ownerOld, s2 pushOwner(c, s2) - var def = semExprWithType(c, a[^1]) - - if def.kind == nkSym and def.sym.kind in {skTemplate, skMacro}: typFlags.incl taIsTemplateOrMacro elif def.typ.kind == tyTypeDesc and c.p.owner.kind != skMacro: diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 2b006e07e9c41..cb7f847a96034 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -487,7 +487,6 @@ proc semTuple(c: PContext, n: PNode, prev: PType): PType = proc semIdentVis(c: PContext, kind: TSymKind, n: PNode, allowed: TSymFlags): PSym = # identifier with visibility - dbgIf n, kind, allowed, n.kind if n.kind == nkPostfix: if n.len == 2: # for gensym'ed identifiers the identifier may already have been @@ -505,7 +504,6 @@ proc semIdentVis(c: PContext, kind: TSymKind, n: PNode, illFormedAst(n, c.config) else: result = newSymG(kind, n, c) - dbgIf result, result.owner proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode, allowed: TSymFlags): PSym = diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index aa123ec5f79c9..37547b6d7adca 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -1500,8 +1500,7 @@ proc checkCanEval(c: PCtx; n: PNode) = # are in the right scope: if sfGenSym in s.flags and c.prc.sym == nil: discard else: - dbg s, s.kind, s.isOwnedBy(c.prc.sym), s.owner, s.owner.kind, c.mode, c.prc.sym, s.flags - # , getCurrOwner(c) + # dbg s, s.kind, s.isOwnedBy(c.prc.sym), s.owner, s.owner.kind, c.mode, c.prc.sym, s.flags cannotEval(c, n) elif s.kind in {skProc, skFunc, skConverter, skMethod, skIterator} and sfForward in s.flags: diff --git a/tests/misc/trfc_276.nim b/tests/misc/trfc_276.nim index daf93521f6236..fd20698c7a06f 100644 --- a/tests/misc/trfc_276.nim +++ b/tests/misc/trfc_276.nim @@ -83,7 +83,7 @@ block: # bug #13887 template fun() = var s = @[10,11,12] let a1 = cast[int](s[0].addr) # 4323682360 - let z = s[0].addr + let z = s[0].addr let a2 = cast[int](z) # 10 => BUG doAssert a1 == a2 static: fun() # fails From 498ffa9cb223ddbcb13cc10297208889e902c4a1 Mon Sep 17 00:00:00 2001 From: Timothee Cour Date: Tue, 3 Aug 2021 10:51:06 -0700 Subject: [PATCH 3/8] cleanup --- compiler/semstmts.nim | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index ea57c23041630..ca6a87b164a56 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -655,6 +655,17 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = if v.flags * {sfGlobal, sfThread} == {sfGlobal}: message(c.config, v.info, hintGlobalVar) +proc pushStaticContext(c: PContext, n: PNode): PSym = + let s2 = newSym(skLabel, c.cache.idAnon, nextSymId c.idgen, c.graph.owners[^1], n.info) + s2.flags.incl sfUsed + result = c.p.owner + c.p.owner = s2 + pushOwner(c, s2) + +proc popStaticContext(c: PContext, ownerOld: PSym) = + c.p.owner = ownerOld + popOwner(c) + proc semConst(c: PContext, n: PNode): PNode = result = copyNode(n) inc c.inStaticContext @@ -672,13 +683,8 @@ proc semConst(c: PContext, n: PNode): PNode = var typFlags: TTypeAllowedFlags # don't evaluate here since the type compatibility check below may add a converter - let s2 = newSym(skLabel, c.cache.idAnon, nextSymId c.idgen, c.graph.owners[^1], n.info) - s2.flags.incl sfUsed - let ownerOld = c.p.owner - c.p.owner = s2 - pushOwner(c, s2) + let ownerOld = pushStaticContext(c, a[^1]) var def = semExprWithType(c, a[^1]) - if def.kind == nkSym and def.sym.kind in {skTemplate, skMacro}: typFlags.incl taIsTemplateOrMacro elif def.typ.kind == tyTypeDesc and c.p.owner.kind != skMacro: @@ -736,8 +742,7 @@ proc semConst(c: PContext, n: PNode): PNode = else: def[j][1] b[j] = newSymNode(v) result.add b - c.p.owner = ownerOld - popOwner(c) + popStaticContext(c, ownerOld) dec c.inStaticContext include semfields From e322bdde24de8af2a67a386348d85b5dbb2fca6c Mon Sep 17 00:00:00 2001 From: Timothee Cour Date: Tue, 3 Aug 2021 11:16:12 -0700 Subject: [PATCH 4/8] fix static; add tests --- compiler/semstmts.nim | 2 ++ tests/misc/trfc_276.nim | 58 +++++++++++++++++++++++++++++++++-------- 2 files changed, 49 insertions(+), 11 deletions(-) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index ca6a87b164a56..1d258ff426960 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -2239,7 +2239,9 @@ proc semStaticStmt(c: PContext, n: PNode): PNode = #writeStackTrace() inc c.inStaticContext openScope(c) + let ownerOld = pushStaticContext(c, n) let a = semStmt(c, n[0], {}) + popStaticContext(c, ownerOld) closeScope(c) dec c.inStaticContext n[0] = a diff --git a/tests/misc/trfc_276.nim b/tests/misc/trfc_276.nim index fd20698c7a06f..b3d29566f6410 100644 --- a/tests/misc/trfc_276.nim +++ b/tests/misc/trfc_276.nim @@ -14,7 +14,7 @@ static: # bug #10938 incl(s, i) block: - # this was causing issues in some variants + # make sure this keeps working (would fail under some implementation variants) const SymChars: set[char] = {'a' .. 'b'} var a = 'x' discard contains(SymChars, a) @@ -106,15 +106,51 @@ block: # bug #12172 test proc test2 = const a3 = block: - let i = 0 # Error here too + let i = 0 # was error here too i -when false: - # xxx this doesn't work yet - block: - proc test = - const a = block: - template fn(x): untyped = - let i = 0 - i - fn(123) +block: + proc test = + const a1 = block: + template fn(x): untyped = + let i = 0 + i + fn(123) + + const a2 = block: + template fn(x): untyped = + let i = 0 + i + fn(123) + + const a3 = block: + template fn(x): untyped = + let i = x + i + fn(123) + doAssert a3 == 123 + +block: # bug #13795 + template fun(): untyped = + var c = 3 + c + proc main() = + const c = fun() + doAssert c == 3 + main() + +when true: # tests with module dependencies + import std / sequtils + # bug #13795 + type SomeEnum = enum + k0 = "foo", k1, k2 + proc fn2(): auto = + const y = SomeEnum.toSeq + y + doAssert fn2() == @[k0, k1, k2] + + proc fn3() = + static: + let z1 = SomeEnum.toSeq + doAssert z1 == @[k0, k1, k2] + fn3() From 147791cdc877d9e7706c5597c030731b284e169a Mon Sep 17 00:00:00 2001 From: Timothee Cour Date: Tue, 3 Aug 2021 11:24:36 -0700 Subject: [PATCH 5/8] add test case for #14645 (partial fix) --- tests/misc/trfc_276.nim | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/misc/trfc_276.nim b/tests/misc/trfc_276.nim index b3d29566f6410..57901643e1d0b 100644 --- a/tests/misc/trfc_276.nim +++ b/tests/misc/trfc_276.nim @@ -140,7 +140,7 @@ block: # bug #13795 main() when true: # tests with module dependencies - import std / sequtils + import std/sequtils # bug #13795 type SomeEnum = enum k0 = "foo", k1, k2 @@ -154,3 +154,20 @@ when true: # tests with module dependencies let z1 = SomeEnum.toSeq doAssert z1 == @[k0, k1, k2] fn3() + +when true: + #[ + bug #14645 (only partial fix) + ]# + import std/strformat + proc re(s: static string): string = s + proc p = + when false: + # xxx still doesn't work: + # internal error: compiler/vmgen.nim(1669, 23) + # internalAssert(c.config, c.prc.regInfo[dest].kind < slotSomeTemp) + const rx1 = re(&"") + const rx2 = re(static(&"")) + static: + # now works + let rx3 = re(&"") From 41508aa5945e6dc73a98e21c82691acfd38551fb Mon Sep 17 00:00:00 2001 From: Timothee Cour Date: Tue, 3 Aug 2021 13:52:31 -0700 Subject: [PATCH 6/8] fix fitsRegister, fix #18641 --- compiler/semstmts.nim | 6 ++++++ compiler/vmgen.nim | 20 ++++++++++++++++--- tests/misc/trfc_276.nim | 37 +++++++++++++++++++++++++++++++++++ tests/stdlib/timportutils.nim | 4 ++++ 4 files changed, 64 insertions(+), 3 deletions(-) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 1d258ff426960..f14ffef2dedaf 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -315,6 +315,7 @@ proc semIdentDef(c: PContext, n: PNode, kind: TSymKind): PSym = else: result = semIdentWithPragma(c, kind, n, {}) if result.owner.kind == skModule: + # if result.owner.kind in {skModule, skLabel}: incl(result.flags, sfGlobal) result.options = c.config.options @@ -2239,8 +2240,13 @@ proc semStaticStmt(c: PContext, n: PNode): PNode = #writeStackTrace() inc c.inStaticContext openScope(c) + # var ownerOld: PSym = nil + # if c.config.isDefined("nim_pushStaticContext"): + # ownerOld = pushStaticContext(c, n) let ownerOld = pushStaticContext(c, n) let a = semStmt(c, n[0], {}) + # if c.config.isDefined("nim_pushStaticContext"): + # popStaticContext(c, ownerOld) popStaticContext(c, ownerOld) closeScope(c) dec c.inStaticContext diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 37547b6d7adca..33f1f6608fa0b 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -614,7 +614,9 @@ proc genCall(c: PCtx; n: PNode; dest: var TDest) = c.gABC(n, opcIndCallAsgn, dest, x, n.len) c.freeTempRange(x, n.len) -template isGlobal(s: PSym): bool = sfGlobal in s.flags and s.kind != skForVar +template isGlobal(s: PSym): bool = + # (sfGlobal in s.flags and s.kind != skForVar) or (s.owner != nil and s.owner.kind == skLabel) + (sfGlobal in s.flags and s.kind != skForVar) proc isGlobal(n: PNode): bool = n.kind == nkSym and isGlobal(n.sym) proc needsAsgnPatch(n: PNode): bool = @@ -986,7 +988,8 @@ proc genBindSym(c: PCtx; n: PNode; dest: var TDest) = proc fitsRegister*(t: PType): bool = assert t != nil t.skipTypes(abstractInst + {tyStatic} - {tyTypeDesc}).kind in { - tyRange, tyEnum, tyBool, tyInt..tyUInt64, tyChar} + # tyRange, tyEnum, tyBool, tyInt..tyUInt64, tyChar} + tyRange, tyEnum, tyBool, tyInt..tyUInt64, tyChar, tyPtr} # PRTEMP proc ldNullOpcode(t: PType): TOpcode = assert t != nil @@ -1634,6 +1637,8 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) = # gfNodeAddr and gfNode are mutually exclusive assert card(flags * {gfNodeAddr, gfNode}) < 2 let s = n.sym + dbgIf s, c.config$n.info, n, s.isGlobal, s.kind, s.owner, flags, s.position, dest + dbgIf getStacktrace() if s.isGlobal: let isImportcVar = importcCondVar(s) if sfCompileTime in s.flags or c.mode == emRepl or isImportcVar: @@ -1666,7 +1671,8 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) = s.kind in {skParam, skResult}): if dest < 0: dest = s.position + ord(s.kind == skParam) - internalAssert(c.config, c.prc.regInfo[dest].kind < slotSomeTemp) + # internalAssert(c.config, c.prc.regInfo[dest].kind < slotSomeTemp) + discard else: # we need to generate an assignment: let requiresCopy = c.prc.regInfo[dest].kind >= slotSomeTemp and @@ -1853,6 +1859,7 @@ proc getNullValue(typ: PType, info: TLineInfo; conf: ConfigRef): PNode = result = newNodeI(nkEmpty, info) proc genVarSection(c: PCtx; n: PNode) = + dbgIf c.config$n.info, n for a in n: if a.kind == nkCommentStmt: continue #assert(a[0].kind == nkSym) can happen for transformed vars @@ -1865,6 +1872,7 @@ proc genVarSection(c: PCtx; n: PNode) = elif a[0].kind == nkSym: let s = a[0].sym checkCanEval(c, a[0]) + dbgIf s, s.kind, s.isGlobal, s.position, a[2].kind if s.isGlobal: if s.position == 0: if importcCond(c, s): c.importcSym(a.info, s) @@ -1876,8 +1884,10 @@ proc genVarSection(c: PCtx; n: PNode) = c.globals.add(sa) s.position = c.globals.len if a[2].kind != nkEmpty: + dbgIf "gfNodeAddr" let tmp = c.genx(a[0], {gfNodeAddr}) let val = c.genx(a[2]) + dbgIf tmp, val c.genAdditionalCopy(a[2], opcWrDeref, tmp, 0, val) c.freeTemp(val) c.freeTemp(tmp) @@ -1887,16 +1897,20 @@ proc genVarSection(c: PCtx; n: PNode) = c.gABx(a, ldNullOpcode(s.typ), s.position, c.genType(s.typ)) else: assert s.typ != nil + dbgIf fitsRegister(s.typ), s.typ if not fitsRegister(s.typ): c.gABx(a, ldNullOpcode(s.typ), s.position, c.genType(s.typ)) let le = a[0] assert le.typ != nil + dbgIf fitsRegister(le.typ), le.typ if not fitsRegister(le.typ) and s.kind in {skResult, skVar, skParam}: + dbgIf "not fitsRegister" var cc = c.getTemp(le.typ) gen(c, a[2], cc) c.gABC(le, whichAsgnOpc(le), s.position.TRegister, cc) c.freeTemp(cc) else: + dbgIf "fitsRegister" gen(c, a[2], s.position.TRegister) else: # assign to a[0]; happens for closures diff --git a/tests/misc/trfc_276.nim b/tests/misc/trfc_276.nim index 57901643e1d0b..62aafbfe15cdb 100644 --- a/tests/misc/trfc_276.nim +++ b/tests/misc/trfc_276.nim @@ -155,6 +155,43 @@ when true: # tests with module dependencies doAssert z1 == @[k0, k1, k2] fn3() +block: # bug #18641 + type A = object + ha1: int + static: + var a = A() + var a2 = a.addr + a2.ha1 = 11 + doAssert a2.ha1 == 11 + a.ha1 = 12 + doAssert a.ha1 == 12 + doAssert a2.ha1 == 12 + static: + proc fn() = + var a = A() + var a2 = a.addr + a2.ha1 = 11 + doAssert a2.ha1 == 11 + a.ha1 = 12 + doAssert a.ha1 == 12 + doAssert a2.ha1 == 12 + fn() + +block: + type A = object + ha1: int + const z = block: + var a = A() + var a2 = a.addr + a2.ha1 = 11 + doAssert a2.ha1 == 11 + a.ha1 = 12 + doAssert a.ha1 == 12 + doAssert a2.ha1 == 12 + 123 + doAssert z == 123 + + when true: #[ bug #14645 (only partial fix) diff --git a/tests/stdlib/timportutils.nim b/tests/stdlib/timportutils.nim index be912e7029945..6b28fa6bc46ce 100644 --- a/tests/stdlib/timportutils.nim +++ b/tests/stdlib/timportutils.nim @@ -1,3 +1,7 @@ +discard """ + joinable: false +""" + import std/importutils import stdtest/testutils import mimportutils From 1cd4dc31fe5ab63fa5e1356c560698a5a9bf0d4a Mon Sep 17 00:00:00 2001 From: Timothee Cour Date: Tue, 3 Aug 2021 14:21:16 -0700 Subject: [PATCH 7/8] fixup --- compiler/vmgen.nim | 5 +++-- tests/tuples/ttuples_issues.nim | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 33f1f6608fa0b..7dda1e1d00365 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -1671,8 +1671,9 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) = s.kind in {skParam, skResult}): if dest < 0: dest = s.position + ord(s.kind == skParam) - # internalAssert(c.config, c.prc.regInfo[dest].kind < slotSomeTemp) - discard + dbgIf c.prc.regInfo, dest, c.prc.regInfo.len, c.prc.sym + internalAssert(c.config, c.prc.regInfo[dest].kind < slotSomeTemp) + # discard else: # we need to generate an assignment: let requiresCopy = c.prc.regInfo[dest].kind >= slotSomeTemp and diff --git a/tests/tuples/ttuples_issues.nim b/tests/tuples/ttuples_issues.nim index 0cc505d28ecfb..0e2a3d965043e 100644 --- a/tests/tuples/ttuples_issues.nim +++ b/tests/tuples/ttuples_issues.nim @@ -5,7 +5,7 @@ discard """ # targets include `cpp` because in the past, there were several cpp-specific bugs with tuples. import std/tables - +{.define(nimCompilerDebug).} template main() = block: # bug #4479 type From b796e9e5a838498c5c87d60e7088a5c3e8284ff5 Mon Sep 17 00:00:00 2001 From: Timothee Cour Date: Tue, 3 Aug 2021 14:35:07 -0700 Subject: [PATCH 8/8] experiment with c.prc = PProc(sym: prc) for D20210803T133907; does not work --- compiler/semstmts.nim | 4 ++++ compiler/vm.nim | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index f14ffef2dedaf..d5b13d7a503dd 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -2244,6 +2244,7 @@ proc semStaticStmt(c: PContext, n: PNode): PNode = # if c.config.isDefined("nim_pushStaticContext"): # ownerOld = pushStaticContext(c, n) let ownerOld = pushStaticContext(c, n) + let ownerNew = c.p.owner let a = semStmt(c, n[0], {}) # if c.config.isDefined("nim_pushStaticContext"): # popStaticContext(c, ownerOld) @@ -2251,7 +2252,10 @@ proc semStaticStmt(c: PContext, n: PNode): PNode = closeScope(c) dec c.inStaticContext n[0] = a + dbgIf c.p.owner, ownerOld, ownerNew evalStaticStmt(c.module, c.idgen, c.graph, a, c.p.owner) + dbgIf "after" + # popStaticContext(c, ownerOld) when false: # for incremental replays, keep the AST as required for replays: result = n diff --git a/compiler/vm.nim b/compiler/vm.nim index b3abe6fb66dfc..ea6910e096d8a 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -2203,6 +2203,8 @@ proc evalConstExprAux(module: PSym; idgen: IdGenerator; c.mode = mode # PRTEMP1 + # let oldPrc = c.prc + # c.prc = PProc(sym: prc) let start = genExpr(c, n, requiresValue = mode!=emStaticStmt) if c.code[start].opcode == opcEof: return newNodeI(nkEmpty, n.info) @@ -2215,6 +2217,8 @@ proc evalConstExprAux(module: PSym; idgen: IdGenerator; if result.info.col < 0: result.info = n.info c.mode = oldMode + # c.prc = oldPrc + proc evalConstExpr*(module: PSym; idgen: IdGenerator; g: ModuleGraph; e: PNode): PNode = result = evalConstExprAux(module, idgen, g, nil, e, emConst)