Fixes for ptr array deref codegen (#11191)
* fixes for ptr array derefence codegen * fix comments, make diff nicer
This commit is contained in:
parent
7804b5c558
commit
a6ba3116b2
4 changed files with 36 additions and 40 deletions
|
|
@ -768,6 +768,8 @@ type
|
||||||
lfHeader, # include header file for symbol
|
lfHeader, # include header file for symbol
|
||||||
lfImportCompilerProc, # ``importc`` of a compilerproc
|
lfImportCompilerProc, # ``importc`` of a compilerproc
|
||||||
lfSingleUse # no location yet and will only be used once
|
lfSingleUse # no location yet and will only be used once
|
||||||
|
lfEnforceDeref # a copyMem is required to dereference if this a
|
||||||
|
# ptr array due to C array limitations. See #1181, #6422, #11171
|
||||||
TStorageLoc* = enum
|
TStorageLoc* = enum
|
||||||
OnUnknown, # location is unknown (stack, heap or static)
|
OnUnknown, # location is unknown (stack, heap or static)
|
||||||
OnStatic, # in a static section
|
OnStatic, # in a static section
|
||||||
|
|
|
||||||
|
|
@ -717,8 +717,10 @@ proc isCppRef(p: BProc; typ: PType): bool {.inline.} =
|
||||||
skipTypes(typ, abstractInstOwned).kind == tyVar and
|
skipTypes(typ, abstractInstOwned).kind == tyVar and
|
||||||
tfVarIsPtr notin skipTypes(typ, abstractInstOwned).flags
|
tfVarIsPtr notin skipTypes(typ, abstractInstOwned).flags
|
||||||
|
|
||||||
proc genDeref(p: BProc, e: PNode, d: var TLoc; enforceDeref=false) =
|
proc genDeref(p: BProc, e: PNode, d: var TLoc) =
|
||||||
let mt = mapType(p.config, e.sons[0].typ)
|
let
|
||||||
|
enforceDeref = lfEnforceDeref in d.flags
|
||||||
|
mt = mapType(p.config, e.sons[0].typ)
|
||||||
if mt in {ctArray, ctPtrToArray} and not enforceDeref:
|
if mt in {ctArray, ctPtrToArray} and not enforceDeref:
|
||||||
# XXX the amount of hacks for C's arrays is incredible, maybe we should
|
# XXX the amount of hacks for C's arrays is incredible, maybe we should
|
||||||
# simply wrap them in a struct? --> Losing auto vectorization then?
|
# simply wrap them in a struct? --> Losing auto vectorization then?
|
||||||
|
|
@ -2343,6 +2345,7 @@ proc genTupleConstr(p: BProc, n: PNode, d: var TLoc) =
|
||||||
if it.kind == nkExprColonExpr: it = it.sons[1]
|
if it.kind == nkExprColonExpr: it = it.sons[1]
|
||||||
initLoc(rec, locExpr, it, d.storage)
|
initLoc(rec, locExpr, it, d.storage)
|
||||||
rec.r = "$1.Field$2" % [rdLoc(d), rope(i)]
|
rec.r = "$1.Field$2" % [rdLoc(d), rope(i)]
|
||||||
|
rec.flags.incl(lfEnforceDeref)
|
||||||
expr(p, it, rec)
|
expr(p, it, rec)
|
||||||
|
|
||||||
proc isConstClosure(n: PNode): bool {.inline.} =
|
proc isConstClosure(n: PNode): bool {.inline.} =
|
||||||
|
|
|
||||||
|
|
@ -123,13 +123,13 @@ proc genVarTuple(p: BProc, n: PNode) =
|
||||||
if forHcr or isGlobalInBlock:
|
if forHcr or isGlobalInBlock:
|
||||||
hcrGlobals.add((loc: v.loc, tp: if traverseProc == nil: ~"NULL" else: traverseProc))
|
hcrGlobals.add((loc: v.loc, tp: if traverseProc == nil: ~"NULL" else: traverseProc))
|
||||||
|
|
||||||
proc genDeref(p: BProc, e: PNode, d: var TLoc; enforceDeref=false)
|
proc genDeref(p: BProc, e: PNode, d: var TLoc)
|
||||||
|
|
||||||
proc loadInto(p: BProc, le, ri: PNode, a: var TLoc) {.inline.} =
|
proc loadInto(p: BProc, le, ri: PNode, a: var TLoc) {.inline.} =
|
||||||
if ri.kind in nkCallKinds and (ri.sons[0].kind != nkSym or
|
if ri.kind in nkCallKinds and (ri.sons[0].kind != nkSym or
|
||||||
ri.sons[0].sym.magic == mNone):
|
ri.sons[0].sym.magic == mNone):
|
||||||
genAsgnCall(p, le, ri, a)
|
genAsgnCall(p, le, ri, a)
|
||||||
elif ri.kind in {nkDerefExpr, nkHiddenDeref}:
|
else:
|
||||||
# this is a hacky way to fix #1181 (tmissingderef)::
|
# this is a hacky way to fix #1181 (tmissingderef)::
|
||||||
#
|
#
|
||||||
# var arr1 = cast[ptr array[4, int8]](addr foo)[]
|
# var arr1 = cast[ptr array[4, int8]](addr foo)[]
|
||||||
|
|
@ -137,8 +137,7 @@ proc loadInto(p: BProc, le, ri: PNode, a: var TLoc) {.inline.} =
|
||||||
# However, fixing this properly really requires modelling 'array' as
|
# However, fixing this properly really requires modelling 'array' as
|
||||||
# a 'struct' in C to preserve dereferencing semantics completely. Not
|
# a 'struct' in C to preserve dereferencing semantics completely. Not
|
||||||
# worth the effort until version 1.0 is out.
|
# worth the effort until version 1.0 is out.
|
||||||
genDeref(p, ri, a, enforceDeref=true)
|
a.flags.incl(lfEnforceDeref)
|
||||||
else:
|
|
||||||
expr(p, ri, a)
|
expr(p, ri, a)
|
||||||
|
|
||||||
proc assignLabel(b: var TBlock): Rope {.inline.} =
|
proc assignLabel(b: var TBlock): Rope {.inline.} =
|
||||||
|
|
@ -597,10 +596,12 @@ proc genWhileStmt(p: BProc, t: PNode) =
|
||||||
dec(p.withinLoop)
|
dec(p.withinLoop)
|
||||||
|
|
||||||
proc genBlock(p: BProc, n: PNode, d: var TLoc) =
|
proc genBlock(p: BProc, n: PNode, d: var TLoc) =
|
||||||
# bug #4505: allocate the temp in the outer scope
|
if not isEmptyType(n.typ):
|
||||||
# so that it can escape the generated {}:
|
# bug #4505: allocate the temp in the outer scope
|
||||||
if not isEmptyType(n.typ) and d.k == locNone:
|
# so that it can escape the generated {}:
|
||||||
getTemp(p, n.typ, d)
|
if d.k == locNone:
|
||||||
|
getTemp(p, n.typ, d)
|
||||||
|
d.flags.incl(lfEnforceDeref)
|
||||||
preserveBreakIdx:
|
preserveBreakIdx:
|
||||||
p.breakIdx = startBlock(p)
|
p.breakIdx = startBlock(p)
|
||||||
if n.sons[0].kind != nkEmpty:
|
if n.sons[0].kind != nkEmpty:
|
||||||
|
|
@ -1232,44 +1233,18 @@ proc asgnFieldDiscriminant(p: BProc, e: PNode) =
|
||||||
genDiscriminantCheck(p, a, tmp, dotExpr.sons[0].typ, dotExpr.sons[1].sym)
|
genDiscriminantCheck(p, a, tmp, dotExpr.sons[0].typ, dotExpr.sons[1].sym)
|
||||||
genAssignment(p, a, tmp, {})
|
genAssignment(p, a, tmp, {})
|
||||||
|
|
||||||
proc patchAsgnStmtListExpr(father, orig, n: PNode) =
|
|
||||||
case n.kind
|
|
||||||
of nkDerefExpr, nkHiddenDeref:
|
|
||||||
let asgn = copyNode(orig)
|
|
||||||
asgn.add orig[0]
|
|
||||||
asgn.add n
|
|
||||||
father.add asgn
|
|
||||||
of nkStmtList, nkStmtListExpr:
|
|
||||||
for x in n:
|
|
||||||
patchAsgnStmtListExpr(father, orig, x)
|
|
||||||
else:
|
|
||||||
father.add n
|
|
||||||
|
|
||||||
proc genAsgn(p: BProc, e: PNode, fastAsgn: bool) =
|
proc genAsgn(p: BProc, e: PNode, fastAsgn: bool) =
|
||||||
if e.sons[0].kind == nkSym and sfGoto in e.sons[0].sym.flags:
|
if e.sons[0].kind == nkSym and sfGoto in e.sons[0].sym.flags:
|
||||||
genLineDir(p, e)
|
genLineDir(p, e)
|
||||||
genGotoVar(p, e.sons[1])
|
genGotoVar(p, e.sons[1])
|
||||||
elif not fieldDiscriminantCheckNeeded(p, e):
|
elif not fieldDiscriminantCheckNeeded(p, e):
|
||||||
# this fixes bug #6422 but we really need to change the representation of
|
|
||||||
# arrays in the backend...
|
|
||||||
let le = e[0]
|
let le = e[0]
|
||||||
let ri = e[1]
|
let ri = e[1]
|
||||||
var needsRepair = false
|
|
||||||
var it = ri
|
|
||||||
while it.kind in {nkStmtList, nkStmtListExpr}:
|
|
||||||
it = it.lastSon
|
|
||||||
needsRepair = true
|
|
||||||
if it.kind in {nkDerefExpr, nkHiddenDeref} and needsRepair:
|
|
||||||
var patchedTree = newNodeI(nkStmtList, e.info)
|
|
||||||
patchAsgnStmtListExpr(patchedTree, e, ri)
|
|
||||||
genStmts(p, patchedTree)
|
|
||||||
return
|
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
discard getTypeDesc(p.module, le.typ.skipTypes(skipPtrs))
|
discard getTypeDesc(p.module, le.typ.skipTypes(skipPtrs))
|
||||||
if le.kind in {nkDerefExpr, nkHiddenDeref}:
|
initLoc(a, locNone, le, OnUnknown)
|
||||||
genDeref(p, le, a, enforceDeref=true)
|
a.flags.incl(lfEnforceDeref)
|
||||||
else:
|
expr(p, le, a)
|
||||||
initLocExpr(p, le, a)
|
|
||||||
if fastAsgn: incl(a.flags, lfNoDeepCopy)
|
if fastAsgn: incl(a.flags, lfNoDeepCopy)
|
||||||
assert(a.t != nil)
|
assert(a.t != nil)
|
||||||
genLineDir(p, ri)
|
genLineDir(p, ri)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
discard """
|
discard """
|
||||||
output: "OK"
|
output: '''[1, 2, 3, 4]
|
||||||
|
3
|
||||||
|
OK
|
||||||
|
'''
|
||||||
"""
|
"""
|
||||||
|
|
||||||
var
|
var
|
||||||
|
|
@ -50,4 +53,17 @@ let aa = getFilledBuffer(3)
|
||||||
for i in 0..aa[].len-1:
|
for i in 0..aa[].len-1:
|
||||||
doAssert(aa[i] == chr(i))
|
doAssert(aa[i] == chr(i))
|
||||||
|
|
||||||
|
var
|
||||||
|
x = [1, 2, 3, 4]
|
||||||
|
y1 = block: (
|
||||||
|
a: (block:
|
||||||
|
echo x
|
||||||
|
cast[ptr array[2, int]](addr(x[0]))[]),
|
||||||
|
b: 3)
|
||||||
|
y2 = block:
|
||||||
|
echo y1.a[0] + y1.a[1]
|
||||||
|
cast[ptr array[4, int]](addr(x))[]
|
||||||
|
doAssert y1 == ([1, 2], 3)
|
||||||
|
doAssert y2 == [1, 2, 3, 4]
|
||||||
|
|
||||||
echo "OK"
|
echo "OK"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue