* Fix #17412

* Address review
This commit is contained in:
Clyybber 2021-03-29 21:16:11 +02:00 • committed by GitHub
commit ed126794b6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 50 additions and 29 deletions

View file

@ -256,32 +256,8 @@ proc addAbiCheck(m: BModule, t: PType, name: Rope) =
m.s[cfsTypeInfo].addf("NIM_STATIC_ASSERT(sizeof($1) == $2, $3);$n", [name, rope(size), msg2.rope]) m.s[cfsTypeInfo].addf("NIM_STATIC_ASSERT(sizeof($1) == $2, $3);$n", [name, rope(size), msg2.rope])
# see `testCodegenABICheck` for example error message it generates # see `testCodegenABICheck` for example error message it generates
proc ccgIntroducedPtr(conf: ConfigRef; s: PSym, retType: PType): bool = from ccgutils import ccgIntroducedPtr
var pt = skipTypes(s.typ, typedescInst) export ccgIntroducedPtr
assert skResult != s.kind
if tfByRef in pt.flags: return true
elif tfByCopy in pt.flags: return false
case pt.kind
of tyObject:
if s.typ.sym != nil and sfForward in s.typ.sym.flags:
# forwarded objects are *always* passed by pointers for consistency!
result = true
elif (optByRef in s.options) or (getSize(conf, pt) > conf.target.floatSize * 3):
result = true # requested anyway
elif (tfFinal in pt.flags) and (pt[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)
else:
result = false
# first parameter and return type is 'lent T'? --> use pass by pointer
if s.position == 0 and retType != nil and retType.kind == tyLent:
result = not (pt.kind in {tyVar, tyArray, tyOpenArray, tyVarargs, tyRef, tyPtr, tyPointer} or
pt.kind == tySet and mapSetType(conf, pt) == ctArray)
proc fillResult(conf: ConfigRef; param: PNode) = proc fillResult(conf: ConfigRef; param: PNode) =
fillLoc(param.sym.loc, locParam, param, ~"Result", fillLoc(param.sym.loc, locParam, param, ~"Result",

View file

@ -10,8 +10,8 @@
# This module declares some helpers for the C code generator. # This module declares some helpers for the C code generator.
import import
ast, hashes, strutils, msgs, wordrecg, ast, types, hashes, strutils, msgs, wordrecg,
platform, trees, options platform, trees, options, cgendata
proc getPragmaStmt*(n: PNode, w: TSpecialWord): PNode = proc getPragmaStmt*(n: PNode, w: TSpecialWord): PNode =
case n.kind case n.kind
@ -106,3 +106,39 @@ proc mangle*(name: string): string =
requiresUnderscore = true requiresUnderscore = true
if requiresUnderscore: if requiresUnderscore:
result.add "_" result.add "_"
proc mapSetType(conf: ConfigRef; typ: PType): TCTypeKind =
case int(getSize(conf, typ))
of 1: result = ctInt8
of 2: result = ctInt16
of 4: result = ctInt32
of 8: result = ctInt64
else: result = ctArray
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
of tyObject:
if s.typ.sym != nil and sfForward in s.typ.sym.flags:
# forwarded objects are *always* passed by pointers for consistency!
result = true
elif (optByRef in s.options) or (getSize(conf, pt) > conf.target.floatSize * 3):
result = true # requested anyway
elif (tfFinal in pt.flags) and (pt[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)
else:
result = false
# first parameter and return type is 'lent T'? --> use pass by pointer
if s.position == 0 and retType != nil and retType.kind == tyLent:
result = not (pt.kind in {tyVar, tyArray, tyOpenArray, tyVarargs, tyRef, tyPtr, tyPointer} or
pt.kind == tySet and mapSetType(conf, pt) == ctArray)

View file

@ -11,7 +11,7 @@
## (``=sink``, ``=``, ``=destroy``, ``=deepCopy``). ## (``=sink``, ``=``, ``=destroy``, ``=deepCopy``).
import modulegraphs, lineinfos, idents, ast, renderer, semdata, import modulegraphs, lineinfos, idents, ast, renderer, semdata,
sighashes, lowerings, options, types, msgs, magicsys, tables sighashes, lowerings, options, types, msgs, magicsys, tables, ccgutils
from trees import isCaseObj from trees import isCaseObj
@ -230,6 +230,15 @@ proc fillBodyObjT(c: var TLiftCtx; t: PType, body, x, y: PNode) =
# for every field (dependent on dest.kind): # for every field (dependent on dest.kind):
# `=` dest.field, src.field # `=` dest.field, src.field
# =destroy(blob) # =destroy(blob)
var dummy = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), nextSymId c.idgen, c.fn, c.info)
dummy.typ = y.typ
if ccgIntroducedPtr(c.g.config, dummy, y.typ):
# Because of potential aliasing when the src param is passed by ref, we need to check for equality here,
# because the wasMoved(dest) call would zero out src, if dest aliases src.
var cond = newTree(nkCall, newSymNode(c.g.getSysMagic(c.info, "==", mEqRef)),
newTreeIT(nkAddr, c.info, makePtrType(c.fn, x.typ, c.idgen), x), newTreeIT(nkAddr, c.info, makePtrType(c.fn, y.typ, c.idgen), y))
cond.typ = getSysType(c.g, x.info, tyBool)
body.add genIf(c, cond, newTreeI(nkReturnStmt, c.info, newNodeI(nkEmpty, c.info)))
var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), nextSymId c.idgen, c.fn, c.info) var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), nextSymId c.idgen, c.fn, c.info)
temp.typ = x.typ temp.typ = x.typ
incl(temp.flags, sfFromGeneric) incl(temp.flags, sfFromGeneric)