diff options
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/ccgcalls.nim | 2 | ||||
-rw-r--r-- | compiler/ccgtypes.nim | 12 | ||||
-rw-r--r-- | compiler/cgen.nim | 14 | ||||
-rw-r--r-- | compiler/parampatterns.nim | 17 |
4 files changed, 29 insertions, 16 deletions
diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim index dd126161d..94cedf339 100644 --- a/compiler/ccgcalls.nim +++ b/compiler/ccgcalls.nim @@ -136,7 +136,7 @@ proc genArg(p: BProc, n: PNode, param: PSym; call: PNode): Rope = elif skipTypes(param.typ, abstractVar).kind in {tyOpenArray, tyVarargs}: var n = if n.kind != nkHiddenAddr: n else: n.sons[0] result = openArrayLoc(p, n) - elif ccgIntroducedPtr(p.config, param): + elif ccgIntroducedPtr(p.config, param, call[0].typ[0]): initLocExpr(p, n, a) result = addrLoc(p.config, a) elif p.module.compileToCpp and param.typ.kind == tyVar and diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index f4864180e..41e04b612 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -249,9 +249,10 @@ proc addAbiCheck(m: BModule, t: PType, name: Rope) = if isDefined(m.config, "checkabi") and (let size = getSize(m.config, t); size != szUnknownSize): addf(m.s[cfsTypeInfo], "NIM_CHECK_SIZE($1, $2);$n", [name, rope(size)]) -proc ccgIntroducedPtr(conf: ConfigRef; s: PSym): bool = +proc ccgIntroducedPtr(conf: ConfigRef; s: PSym, retType: PType): bool = var pt = skipTypes(s.typ, typedescInst) assert skResult != s.kind + if tfByRef in pt.flags: return true elif tfByCopy in pt.flags: return false case pt.kind @@ -261,13 +262,18 @@ proc ccgIntroducedPtr(conf: ConfigRef; s: PSym): bool = result = true elif (optByRef in s.options) or (getSize(conf, pt) > conf.target.floatSize * 3): result = true # requested anyway + elif retType != nil and retType.kind == tyLent: + result = true elif (tfFinal in pt.flags) and (pt.sons[0] == nil): result = false # no need, because no subtyping possible else: result = true # ordinary objects are always passed by reference, # otherwise casting doesn't work of tyTuple: - result = (getSize(conf, pt) > conf.target.floatSize*3) or (optByRef in s.options) + if retType != nil and retType.kind == tyLent: + result = true + else: + result = (getSize(conf, pt) > conf.target.floatSize*3) or (optByRef in s.options) else: result = false proc fillResult(conf: ConfigRef; param: PNode) = @@ -404,7 +410,7 @@ proc genProcParams(m: BModule, t: PType, rettype, params: var Rope, if params != nil: add(params, ~", ") fillLoc(param.loc, locParam, t.n.sons[i], mangleParamName(m, param), param.paramStorageLoc) - if ccgIntroducedPtr(m.config, param): + if ccgIntroducedPtr(m.config, param, t.sons[0]): add(params, getTypeDescWeak(m, param.typ, check)) add(params, ~"*") incl(param.loc.flags, lfIndirect) diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 18e0b1c68..da5e3603b 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -411,12 +411,12 @@ proc deinitGCFrame(p: BProc): Rope = result = ropecg(p.module, "if (((NU)&GCFRAME_) < 4096) #nimGCFrame(&GCFRAME_);$n") -proc localDebugInfo(p: BProc, s: PSym) = +proc localDebugInfo(p: BProc, s: PSym, retType: PType) = if {optStackTrace, optEndb} * p.options != {optStackTrace, optEndb}: return # XXX work around a bug: No type information for open arrays possible: if skipTypes(s.typ, abstractVar).kind in {tyOpenArray, tyVarargs}: return var a = "&" & s.loc.r - if s.kind == skParam and ccgIntroducedPtr(p.config, s): a = s.loc.r + if s.kind == skParam and ccgIntroducedPtr(p.config, s, retType): a = s.loc.r lineF(p, cpsInit, "FR_.s[$1].address = (void*)$3; FR_.s[$1].typ = $4; FR_.s[$1].name = $2;$n", [p.maxFrameLen.rope, makeCString(normalize(s.name.s)), a, @@ -447,7 +447,7 @@ proc assignLocalVar(p: BProc, n: PNode) = let nl = if optLineDir in p.config.options: "" else: "\L" let decl = localVarDecl(p, n) & ";" & nl line(p, cpsLocals, decl) - localDebugInfo(p, n.sym) + localDebugInfo(p, n.sym, nil) include ccgthreadvars @@ -501,10 +501,10 @@ proc assignGlobalVar(p: BProc, n: PNode) = [makeCString(normalize(s.owner.name.s & '.' & s.name.s)), s.loc.r, genTypeInfo(p.module, s.typ, n.info)]) -proc assignParam(p: BProc, s: PSym) = +proc assignParam(p: BProc, s: PSym, retType: PType) = assert(s.loc.r != nil) scopeMangledParam(p, s) - localDebugInfo(p, s) + localDebugInfo(p, s, retType) proc fillProcLoc(m: BModule; n: PNode) = let sym = n.sym @@ -934,7 +934,7 @@ proc genProcAux(m: BModule, prc: PSym) = returnStmt = ropecg(p.module, "\treturn $1;$n", rdLoc(res.loc)) else: fillResult(p.config, resNode) - assignParam(p, res) + assignParam(p, res, prc.typ[0]) # We simplify 'unsureAsgn(result, nil); unsureAsgn(result, x)' # to 'unsureAsgn(result, x)' # Sketch why this is correct: If 'result' points to a stack location @@ -952,7 +952,7 @@ proc genProcAux(m: BModule, prc: PSym) = for i in countup(1, sonsLen(prc.typ.n) - 1): let param = prc.typ.n.sons[i].sym if param.typ.isCompileTimeOnly: continue - assignParam(p, param) + assignParam(p, param, prc.typ[0]) closureSetup(p, prc) genStmts(p, procBody) # modifies p.locals, p.init, etc. var generatedProc: Rope diff --git a/compiler/parampatterns.nim b/compiler/parampatterns.nim index db79e3eb9..b4409fcec 100644 --- a/compiler/parampatterns.nim +++ b/compiler/parampatterns.nim @@ -230,8 +230,10 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult let t = n.sym.typ.skipTypes({tyTypeDesc}) if t.kind == tyVar: result = arStrange of nkDotExpr: - if skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc}).kind in - {tyVar, tyPtr, tyRef}: + let t = skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc}) + if t.kind in {tyVar, tyPtr, tyRef}: + result = arLValue + elif isUnsafeAddr and t.kind == tyLent: result = arLValue else: result = isAssignable(owner, n.sons[0], isUnsafeAddr) @@ -239,8 +241,10 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult sfDiscriminant in n[1].sym.flags: result = arDiscriminant of nkBracketExpr: - if skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc}).kind in - {tyVar, tyPtr, tyRef}: + let t = skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc}) + if t.kind in {tyVar, tyPtr, tyRef}: + result = arLValue + elif isUnsafeAddr and t.kind == tyLent: result = arLValue else: result = isAssignable(owner, n.sons[0], isUnsafeAddr) @@ -254,7 +258,8 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult # types that are equal modulo distinction preserve l-value: result = isAssignable(owner, n.sons[1], isUnsafeAddr) of nkHiddenDeref: - if n[0].typ.kind == tyLent: result = arDiscriminant + if isUnsafeAddr and n[0].typ.kind == tyLent: result = arLValue + elif n[0].typ.kind == tyLent: result = arDiscriminant else: result = arLValue of nkDerefExpr, nkHiddenAddr: result = arLValue @@ -266,6 +271,8 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult result = isAssignable(owner, n.sons[1], isUnsafeAddr) elif n.typ != nil and n.typ.kind == tyVar: result = arLValue + elif isUnsafeAddr and n.typ != nil and n.typ.kind == tyLent: + result = arLValue of nkStmtList, nkStmtListExpr: if n.typ != nil: result = isAssignable(owner, n.lastSon, isUnsafeAddr) |