diff options
author | Araq <rumpf_a@web.de> | 2018-08-04 15:52:34 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2018-08-04 15:52:34 +0200 |
commit | 9235f7a3b39704a1a2e93602971e38bd93d80f3e (patch) | |
tree | 321234aa955a07a9ae656d49cc196a6babe47ec6 /compiler | |
parent | 1c80619ac528f4ec30ee882cb9232157a6763add (diff) | |
parent | e403ef25aceed929a3118e0dc2104c29e824dfcd (diff) | |
download | Nim-9235f7a3b39704a1a2e93602971e38bd93d80f3e.tar.gz |
Merge branch 'devel' into araq-fixes-7833
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/docgen.nim | 9 | ||||
-rw-r--r-- | compiler/extccomp.nim | 7 | ||||
-rw-r--r-- | compiler/lineinfos.nim | 5 | ||||
-rw-r--r-- | compiler/modulepaths.nim | 1 | ||||
-rw-r--r-- | compiler/options.nim | 7 | ||||
-rw-r--r-- | compiler/semmagic.nim | 67 | ||||
-rw-r--r-- | compiler/semtypes.nim | 1 | ||||
-rw-r--r-- | compiler/vm.nim | 29 | ||||
-rw-r--r-- | compiler/vmdef.nim | 5 | ||||
-rw-r--r-- | compiler/vmgen.nim | 133 |
10 files changed, 186 insertions, 78 deletions
diff --git a/compiler/docgen.nim b/compiler/docgen.nim index 2c0208b36..8d233566c 100644 --- a/compiler/docgen.nim +++ b/compiler/docgen.nim @@ -517,12 +517,11 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) = path = path[cwd.len+1 .. ^1].replace('\\', '/') let gitUrl = getConfigVar(d.conf, "git.url") if gitUrl.len > 0: - var commit = getConfigVar(d.conf, "git.commit") - if commit.len == 0: commit = "master" + let commit = getConfigVar(d.conf, "git.commit", "master") + let develBranch = getConfigVar(d.conf, "git.devel", "devel") dispA(d.conf, seeSrcRope, "$1", "", [ropeFormatNamedVars(d.conf, docItemSeeSrc, - ["path", "line", "url", "commit"], [rope path, - rope($n.info.line), rope gitUrl, - rope commit])]) + ["path", "line", "url", "commit", "devel"], [rope path, + rope($n.info.line), rope gitUrl, rope commit, rope develBranch])]) add(d.section[k], ropeFormatNamedVars(d.conf, getConfigVar(d.conf, "doc.item"), ["name", "header", "desc", "itemID", "header_plain", "itemSym", diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim index f4ef93070..16b0d614d 100644 --- a/compiler/extccomp.nim +++ b/compiler/extccomp.nim @@ -645,7 +645,7 @@ proc compileCFile(conf: ConfigRef; list: CFileList, script: var Rope, cmds: var if optCompileOnly notin conf.globalOptions: add(cmds, compileCmd) let (_, name, _) = splitFile(it.cname) - add(prettyCmds, "CC: " & name) + add(prettyCmds, if hintCC in conf.notes: "CC: " & name else: "") if optGenScript in conf.globalOptions: add(script, compileCmd) add(script, "\n") @@ -659,7 +659,7 @@ proc getLinkCmd(conf: ConfigRef; projectfile, objfiles: string): string = libname = getCurrentDir() / libname else: libname = (libNameTmpl(conf) % splitFile(conf.projectName).name) - result = CC[conf.cCompiler].buildLib % ["libfile", libname, + result = CC[conf.cCompiler].buildLib % ["libfile", quoteShell(libname), "objfiles", objfiles] else: var linkerExe = getConfigVar(conf, conf.cCompiler, ".linkerexe") @@ -773,7 +773,8 @@ proc callCCompiler*(conf: ConfigRef; projectfile: string) = var prettyCmds: TStringSeq = @[] let prettyCb = proc (idx: int) = when declared(echo): - echo prettyCmds[idx] + let cmd = prettyCmds[idx] + if cmd != "": echo cmd compileCFile(conf, conf.toCompile, script, cmds, prettyCmds) if optCompileOnly notin conf.globalOptions: execCmdsInParallel(conf, cmds, prettyCb) diff --git a/compiler/lineinfos.nim b/compiler/lineinfos.nim index b8678e6ba..261dcb44e 100644 --- a/compiler/lineinfos.nim +++ b/compiler/lineinfos.nim @@ -37,7 +37,7 @@ type warnProveInit, warnProveField, warnProveIndex, warnGcUnsafe, warnGcUnsafe2, warnUninit, warnGcMem, warnDestructor, warnLockLevel, warnResultShadowed, warnInconsistentSpacing, warnUser, - hintSuccess, hintSuccessX, + hintSuccess, hintSuccessX, hintCC, hintLineTooLong, hintXDeclaredButNotUsed, hintConvToBaseNotNeeded, hintConvFromXtoItselfNotNeeded, hintExprAlwaysX, hintQuitCalled, hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintPath, @@ -94,6 +94,7 @@ const warnUser: "$1", hintSuccess: "operation successful", hintSuccessX: "operation successful ($# lines compiled; $# sec total; $#; $#)", + hintCC: "CC: \'$1\'", # unused hintLineTooLong: "line too long", hintXDeclaredButNotUsed: "'$1' is declared but not used", hintConvToBaseNotNeeded: "conversion to base object is not needed", @@ -136,7 +137,7 @@ const "Spacing", "User"] HintsToStr* = [ - "Success", "SuccessX", "LineTooLong", + "Success", "SuccessX", "CC", "LineTooLong", "XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded", "ExprAlwaysX", "QuitCalled", "Processing", "CodeBegin", "CodeEnd", "Conf", "Path", "CondTrue", "Name", "Pattern", "Exec", "Link", "Dependency", diff --git a/compiler/modulepaths.nim b/compiler/modulepaths.nim index ef0831ad6..e5cbf3a2c 100644 --- a/compiler/modulepaths.nim +++ b/compiler/modulepaths.nim @@ -155,6 +155,7 @@ proc getModuleName*(conf: ConfigRef; n: PNode): string = # hacky way to implement 'x / y /../ z': result = renderTree(n, {renderNoComments}).replace(" ") of nkDotExpr: + localError(conf, n.info, warnDeprecated, "using '.' instead of '/' in import paths") result = renderTree(n, {renderNoComments}).replace(".", "/") of nkImportAs: result = getModuleName(conf, n.sons[0]) diff --git a/compiler/options.nim b/compiler/options.nim index 7cca40321..598adf27d 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -116,7 +116,8 @@ type callOperator, parallel, destructor, - notnil + notnil, + dynamicBindSym SymbolFilesOption* = enum disabledSf, writeOnlySf, readOnlySf, v2Sf @@ -406,8 +407,8 @@ proc mainCommandArg*(conf: ConfigRef): string = proc existsConfigVar*(conf: ConfigRef; key: string): bool = result = hasKey(conf.configVars, key) -proc getConfigVar*(conf: ConfigRef; key: string): string = - result = conf.configVars.getOrDefault key +proc getConfigVar*(conf: ConfigRef; key: string, default = ""): string = + result = conf.configVars.getOrDefault(key, default) proc setConfigVar*(conf: ConfigRef; key, val: string) = conf.configVars[key] = val diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index b5875c67a..8bfa5545e 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -207,6 +207,67 @@ proc semBindSym(c: PContext, n: PNode): PNode = else: errorUndeclaredIdentifier(c, n.sons[1].info, sl.strVal) +proc opBindSym(c: PContext, scope: PScope, n: PNode, isMixin: int, info: PNode): PNode = + if n.kind notin {nkStrLit, nkRStrLit, nkTripleStrLit, nkIdent}: + localError(c.config, info.info, errStringOrIdentNodeExpected) + return errorNode(c, n) + + if isMixin < 0 or isMixin > high(TSymChoiceRule).int: + localError(c.config, info.info, errConstExprExpected) + return errorNode(c, n) + + let id = if n.kind == nkIdent: n + else: newIdentNode(getIdent(c.cache, n.strVal), info.info) + + let tmpScope = c.currentScope + c.currentScope = scope + let s = qualifiedLookUp(c, id, {checkUndeclared}) + if s != nil: + # we need to mark all symbols: + result = symChoice(c, id, s, TSymChoiceRule(isMixin)) + else: + errorUndeclaredIdentifier(c, info.info, if n.kind == nkIdent: n.ident.s + else: n.strVal) + c.currentScope = tmpScope + +proc semDynamicBindSym(c: PContext, n: PNode): PNode = + # inside regular code, bindSym resolves to the sym-choice + # nodes (see tinspectsymbol) + if not (c.inStaticContext > 0 or getCurrOwner(c).isCompileTimeProc): + return semBindSym(c, n) + + if c.graph.vm.isNil: + setupGlobalCtx(c.module, c.graph) + + let + vm = PCtx c.graph.vm + # cache the current scope to + # prevent it lost into oblivion + scope = c.currentScope + + # cannot use this + # vm.config.features.incl dynamicBindSym + + proc bindSymWrapper(a: VmArgs) = + # capture PContext and currentScope + # param description: + # 0. ident, a string literal / computed string / or ident node + # 1. bindSym rule + # 2. info node + a.setResult opBindSym(c, scope, a.getNode(0), a.getInt(1).int, a.getNode(2)) + + let + # altough we use VM callback here, it is not + # executed like 'normal' VM callback + idx = vm.registerCallback("bindSymImpl", bindSymWrapper) + # dummy node to carry idx information to VM + idxNode = newIntTypeNode(nkIntLit, idx, c.graph.getSysType(TLineInfo(), tyInt)) + + result = copyNode(n) + for x in n: result.add x + result.add n # info node + result.add idxNode + proc semShallowCopy(c: PContext, n: PNode, flags: TExprFlags): PNode proc semOf(c: PContext, n: PNode): PNode = @@ -270,7 +331,11 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode, of mOf: result = semOf(c, n) of mHigh, mLow: result = semLowHigh(c, n, n[0].sym.magic) of mShallowCopy: result = semShallowCopy(c, n, flags) - of mNBindSym: result = semBindSym(c, n) + of mNBindSym: + if dynamicBindSym notin c.features: + result = semBindSym(c, n) + else: + result = semDynamicBindSym(c, n) of mProcCall: result = n result.typ = n[1].typ diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 24896e944..972c8c709 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -11,6 +11,7 @@ # included from sem.nim const + errStringOrIdentNodeExpected = "string or ident node expected" errStringLiteralExpected = "string literal expected" errIntLiteralExpected = "integer literal expected" errWrongNumberOfVariables = "wrong number of variables" diff --git a/compiler/vm.nim b/compiler/vm.nim index 373a64e39..a6ec4788b 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -616,19 +616,12 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = let rc = instr.regC case regs[ra].kind of rkNodeAddr: - # XXX: Workaround for vmgen bug: let n = regs[rc].regToNode - if (nfIsRef in regs[ra].nodeAddr[].flags or - regs[ra].nodeAddr[].kind == nkNilLit) and nfIsRef notin n.flags: - if regs[ra].nodeAddr[].kind == nkNilLit: - stackTrace(c, tos, pc, errNilAccess) - regs[ra].nodeAddr[][] = n[] - regs[ra].nodeAddr[].flags.incl nfIsRef # `var object` parameters are sent as rkNodeAddr. When they are mutated # vmgen generates opcWrDeref, which means that we must dereference # twice. # TODO: This should likely be handled differently in vmgen. - elif (nfIsRef notin regs[ra].nodeAddr[].flags and + if (nfIsRef notin regs[ra].nodeAddr[].flags and nfIsRef notin n.flags): regs[ra].nodeAddr[][] = n[] else: @@ -1229,9 +1222,25 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = node.typ.callConv == ccClosure and node.sons[0].kind == nkNilLit and node.sons[1].kind == nkNilLit)) of opcNBindSym: + # cannot use this simple check + # if dynamicBindSym notin c.config.features: + + # bindSym with static input decodeBx(rkNode) regs[ra].node = copyTree(c.constants.sons[rbx]) regs[ra].node.flags.incl nfIsRef + of opcNDynBindSym: + # experimental bindSym + let + rb = instr.regB + rc = instr.regC + idx = int(regs[rb+rc-1].intVal) + callback = c.callbacks[idx].value + args = VmArgs(ra: ra, rb: rb, rc: rc, slots: cast[pointer](regs), + currentException: c.currentExceptionB, + currentLineInfo: c.debug[pc]) + callback(args) + regs[ra].node.flags.incl nfIsRef of opcNChild: decodeBC(rkNode) let idx = regs[rc].intVal.int @@ -1416,7 +1425,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = of opcNGetFile: decodeB(rkNode) let n = regs[rb].node - regs[ra].node = newStrNode(nkStrLit, toFilename(c.config, n.info)) + regs[ra].node = newStrNode(nkStrLit, toFullPath(c.config, n.info)) regs[ra].node.info = n.info regs[ra].node.typ = n.typ of opcNGetLine: @@ -1780,7 +1789,7 @@ proc getGlobalValue*(c: PCtx; s: PSym): PNode = include vmops -proc setupGlobalCtx(module: PSym; graph: ModuleGraph) = +proc setupGlobalCtx*(module: PSym; graph: ModuleGraph) = if graph.vm.isNil: graph.vm = newCtx(module, graph.cache, graph) registerAdditionalOps(PCtx graph.vm) diff --git a/compiler/vmdef.nim b/compiler/vmdef.nim index f7466b392..866b79568 100644 --- a/compiler/vmdef.nim +++ b/compiler/vmdef.nim @@ -136,7 +136,7 @@ type opcLdGlobalAddr, # dest = addr(globals[Bx]) opcLdImmInt, # dest = immediate value - opcNBindSym, + opcNBindSym, opcNDynBindSym, opcSetType, # dest.typ = types[Bx] opcTypeTrait, opcMarshalLoad, opcMarshalStore, @@ -229,7 +229,8 @@ proc refresh*(c: PCtx, module: PSym) = c.prc = PProc(blocks: @[]) c.loopIterations = MaxLoopIterations -proc registerCallback*(c: PCtx; name: string; callback: VmCallback) = +proc registerCallback*(c: PCtx; name: string; callback: VmCallback): int {.discardable.} = + result = c.callbacks.len c.callbacks.add((name, callback)) const diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index d2243376c..3b5ea4beb 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -37,7 +37,9 @@ when hasFFI: import evalffi type - TGenFlag = enum gfAddrOf, gfFieldAccess + TGenFlag = enum + gfNode # Affects how variables are loaded - always loads as rkNode + gfNodeAddr # Affects how variables are loaded - always loads as rkNodeAddr TGenFlags = set[TGenFlag] proc debugInfo(c: PCtx; info: TLineInfo): string = @@ -563,7 +565,7 @@ proc genIndex(c: PCtx; n: PNode; arr: PType): TRegister = proc genAsgnPatch(c: PCtx; le: PNode, value: TRegister) = case le.kind of nkBracketExpr: - let dest = c.genx(le.sons[0], {gfAddrOf, gfFieldAccess}) + let dest = c.genx(le.sons[0], {gfNode}) let idx = c.genIndex(le.sons[1], le.sons[0].typ) c.gABC(le, opcWrArr, dest, idx, value) c.freeTemp(dest) @@ -571,17 +573,17 @@ proc genAsgnPatch(c: PCtx; le: PNode, value: TRegister) = of nkDotExpr, nkCheckedFieldExpr: # XXX field checks here let left = if le.kind == nkDotExpr: le else: le.sons[0] - let dest = c.genx(left.sons[0], {gfAddrOf, gfFieldAccess}) + let dest = c.genx(left.sons[0], {gfNode}) let idx = genField(c, left.sons[1]) c.gABC(left, opcWrObj, dest, idx, value) c.freeTemp(dest) of nkDerefExpr, nkHiddenDeref: - let dest = c.genx(le.sons[0], {gfAddrOf}) + let dest = c.genx(le.sons[0], {gfNode}) c.gABC(le, opcWrDeref, dest, 0, value) c.freeTemp(dest) of nkSym: if le.sym.isGlobal: - let dest = c.genx(le, {gfAddrOf}) + let dest = c.genx(le, {gfNodeAddr}) c.gABC(le, opcWrDeref, dest, 0, value) c.freeTemp(dest) else: @@ -815,6 +817,43 @@ proc genVoidABC(c: PCtx, n: PNode, dest: TDest, opcode: TOpcode) = c.freeTemp(tmp2) c.freeTemp(tmp3) +proc genBindSym(c: PCtx; n: PNode; dest: var TDest) = + # nah, cannot use c.config.features because sempass context + # can have local experimental switch + # if dynamicBindSym notin c.config.features: + if n.len == 2: # hmm, reliable? + # bindSym with static input + if n[1].kind in {nkClosedSymChoice, nkOpenSymChoice, nkSym}: + let idx = c.genLiteral(n[1]) + if dest < 0: dest = c.getTemp(n.typ) + c.gABx(n, opcNBindSym, dest, idx) + else: + localError(c.config, n.info, "invalid bindSym usage") + else: + # experimental bindSym + if dest < 0: dest = c.getTemp(n.typ) + let x = c.getTempRange(n.len, slotTempUnknown) + + # callee symbol + var tmp0 = TDest(x) + c.genLit(n.sons[0], tmp0) + + # original parameters + for i in 1..<n.len-2: + var r = TRegister(x+i) + c.gen(n.sons[i], r) + + # info node + var tmp1 = TDest(x+n.len-2) + c.genLit(n.sons[^2], tmp1) + + # payload idx + var tmp2 = TDest(x+n.len-1) + c.genLit(n.sons[^1], tmp2) + + c.gABC(n, opcNDynBindSym, dest, x, n.len) + c.freeTempRange(x, n.len) + proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) = case m of mAnd: c.genAndOr(n, opcFJmp, dest) @@ -1135,13 +1174,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) = of mNNewNimNode: genBinaryABC(c, n, dest, opcNNewNimNode) of mNCopyNimNode: genUnaryABC(c, n, dest, opcNCopyNimNode) of mNCopyNimTree: genUnaryABC(c, n, dest, opcNCopyNimTree) - of mNBindSym: - if n[1].kind in {nkClosedSymChoice, nkOpenSymChoice, nkSym}: - let idx = c.genLiteral(n[1]) - if dest < 0: dest = c.getTemp(n.typ) - c.gABx(n, opcNBindSym, dest, idx) - else: - localError(c.config, n.info, "invalid bindSym usage") + of mNBindSym: genBindSym(c, n, dest) of mStrToIdent: genUnaryABC(c, n, dest, opcStrToIdent) of mEqIdent: genBinaryABC(c, n, dest, opcEqIdent) of mEqNimrodNode: genBinaryABC(c, n, dest, opcEqNimrodNode) @@ -1252,41 +1285,21 @@ proc canElimAddr(n: PNode): PNode = # addr ( deref ( x )) --> x result = n.sons[0].sons[0] -proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode; - flags: TGenFlags) = - # a nop for certain types - let isAddr = opc in {opcAddrNode, opcAddrReg} - if isAddr and (let m = canElimAddr(n); m != nil): +proc genAddr(c: PCtx, n: PNode, dest: var TDest, flags: TGenFlags) = + if (let m = canElimAddr(n); m != nil): gen(c, m, dest, flags) return - let af = if n[0].kind in {nkBracketExpr, nkDotExpr, nkCheckedFieldExpr}: {gfAddrOf, gfFieldAccess} - else: {gfAddrOf} - let newflags = if isAddr: flags+af else: flags - # consider: - # proc foo(f: var ref int) = - # f = new(int) - # proc blah() = - # var x: ref int - # foo x - # - # The type of 'f' is 'var ref int' and of 'x' is 'ref int'. Hence for - # nkAddr we must not use 'unneededIndirection', but for deref we use it. - if not isAddr and unneededIndirection(n.sons[0]): - gen(c, n.sons[0], dest, newflags) - if gfAddrOf notin flags and fitsRegister(n.typ): - c.gABC(n, opcNodeToReg, dest, dest) - elif isAddr and isGlobal(n.sons[0]): + let af = if n[0].kind in {nkBracketExpr, nkDotExpr, nkCheckedFieldExpr}: {gfNode} + else: {gfNodeAddr} + let newflags = flags-{gfNode, gfNodeAddr}+af + + if isGlobal(n.sons[0]): gen(c, n.sons[0], dest, flags+af) else: let tmp = c.genx(n.sons[0], newflags) if dest < 0: dest = c.getTemp(n.typ) - if not isAddr: - gABC(c, n, opc, dest, tmp) - assert n.typ != nil - if gfAddrOf notin flags and fitsRegister(n.typ): - c.gABC(n, opcNodeToReg, dest, dest) - elif c.prc.slots[tmp].kind >= slotTempUnknown: + if c.prc.slots[tmp].kind >= slotTempUnknown: gABC(c, n, opcAddrNode, dest, tmp) # hack ahead; in order to fix bug #1781 we mark the temporary as # permanent, so that it's not used for anything else: @@ -1297,6 +1310,19 @@ proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode; gABC(c, n, opcAddrReg, dest, tmp) c.freeTemp(tmp) +proc genDeref(c: PCtx, n: PNode, dest: var TDest, flags: TGenFlags) = + if unneededIndirection(n.sons[0]): + gen(c, n.sons[0], dest, flags) + if {gfNodeAddr, gfNode} * flags == {} and fitsRegister(n.typ): + c.gABC(n, opcNodeToReg, dest, dest) + else: + let tmp = c.genx(n.sons[0], flags) + if dest < 0: dest = c.getTemp(n.typ) + gABC(c, n, opcLdDeref, dest, tmp) + assert n.typ != nil + if {gfNodeAddr, gfNode} * flags == {} and fitsRegister(n.typ): + c.gABC(n, opcNodeToReg, dest, dest) + proc whichAsgnOpc(n: PNode): TOpcode = case n.typ.skipTypes(abstractRange-{tyTypeDesc}).kind of tyBool, tyChar, tyEnum, tyOrdinal, tyInt..tyInt64, tyUInt..tyUInt64: @@ -1382,7 +1408,7 @@ proc preventFalseAlias(c: PCtx; n: PNode; opc: TOpcode; proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) = case le.kind of nkBracketExpr: - let dest = c.genx(le.sons[0], {gfAddrOf, gfFieldAccess}) + let dest = c.genx(le.sons[0], {gfNode}) let idx = c.genIndex(le.sons[1], le.sons[0].typ) let tmp = c.genx(ri) if le.sons[0].typ.skipTypes(abstractVarRange-{tyTypeDesc}).kind in { @@ -1394,13 +1420,13 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) = of nkDotExpr, nkCheckedFieldExpr: # XXX field checks here let left = if le.kind == nkDotExpr: le else: le.sons[0] - let dest = c.genx(left.sons[0], {gfAddrOf, gfFieldAccess}) + let dest = c.genx(left.sons[0], {gfNode}) let idx = genField(c, left.sons[1]) let tmp = c.genx(ri) c.preventFalseAlias(left, opcWrObj, dest, idx, tmp) c.freeTemp(tmp) of nkDerefExpr, nkHiddenDeref: - let dest = c.genx(le.sons[0], {gfAddrOf}) + let dest = c.genx(le.sons[0], {gfNode}) let tmp = c.genx(ri) c.preventFalseAlias(le, opcWrDeref, dest, 0, tmp) c.freeTemp(tmp) @@ -1409,7 +1435,7 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) = checkCanEval(c, le) if s.isGlobal: withTemp(tmp, le.typ): - c.gen(le, tmp, {gfAddrOf}) + c.gen(le, tmp, {gfNodeAddr}) let val = c.genx(ri) c.preventFalseAlias(le, opcWrDeref, tmp, 0, val) c.freeTemp(val) @@ -1427,7 +1453,7 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) = else: gen(c, ri, dest) else: - let dest = c.genx(le, {gfAddrOf}) + let dest = c.genx(le, {gfNodeAddr}) genAsgn(c, dest, ri, requiresCopy) proc genTypeLit(c: PCtx; t: PType; dest: var TDest) = @@ -1463,6 +1489,8 @@ proc genGlobalInit(c: PCtx; n: PNode; s: PSym) = c.freeTemp(tmp) 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 if s.isGlobal: if sfCompileTime in s.flags or c.mode == emRepl: @@ -1474,13 +1502,13 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) = else: genGlobalInit(c, n, s) if dest < 0: dest = c.getTemp(n.typ) assert s.typ != nil - if gfAddrOf notin flags and fitsRegister(s.typ): + if gfNodeAddr in flags: + c.gABx(n, opcLdGlobalAddr, dest, s.position) + elif fitsRegister(s.typ) and gfNode notin flags: var cc = c.getTemp(n.typ) c.gABx(n, opcLdGlobal, cc, s.position) c.gABC(n, opcNodeToReg, dest, cc) c.freeTemp(cc) - elif {gfAddrOf, gfFieldAccess} * flags == {gfAddrOf}: - c.gABx(n, opcLdGlobalAddr, dest, s.position) else: c.gABx(n, opcLdGlobal, dest, s.position) else: @@ -1498,7 +1526,8 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) = cannotEval(c, n) template needsRegLoad(): untyped = - gfAddrOf notin flags and fitsRegister(n.typ.skipTypes({tyVar, tyLent})) + {gfNode, gfNodeAddr} * flags == {} and + fitsRegister(n.typ.skipTypes({tyVar, tyLent})) proc genArrAccess2(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode; flags: TGenFlags) = @@ -1634,7 +1663,7 @@ proc genVarSection(c: PCtx; n: PNode) = c.globals.add(sa) s.position = c.globals.len if a.sons[2].kind != nkEmpty: - let tmp = c.genx(a.sons[0], {gfAddrOf}) + let tmp = c.genx(a.sons[0], {gfNodeAddr}) let val = c.genx(a.sons[2]) c.genAdditionalCopy(a.sons[2], opcWrDeref, tmp, 0, val) c.freeTemp(val) @@ -1839,8 +1868,8 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) = of nkDotExpr: genObjAccess(c, n, dest, flags) of nkCheckedFieldExpr: genCheckedObjAccess(c, n, dest, flags) of nkBracketExpr: genArrAccess(c, n, dest, flags) - of nkDerefExpr, nkHiddenDeref: genAddrDeref(c, n, dest, opcLdDeref, flags) - of nkAddr, nkHiddenAddr: genAddrDeref(c, n, dest, opcAddrNode, flags) + of nkDerefExpr, nkHiddenDeref: genDeref(c, n, dest, flags) + of nkAddr, nkHiddenAddr: genAddr(c, n, dest, flags) of nkIfStmt, nkIfExpr: genIf(c, n, dest) of nkWhenStmt: # This is "when nimvm" node. Chose the first branch. |