summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/ccgcalls.nim2
-rw-r--r--compiler/ccgtypes.nim12
-rw-r--r--compiler/cgen.nim14
-rw-r--r--compiler/parampatterns.nim17
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)