diff options
author | Jasper Jenkins <jasper.vs.jenkins@gmail.com> | 2019-05-06 23:14:38 -0700 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2019-05-07 08:14:38 +0200 |
commit | a6ba3116b2376d9f3476ef0f8db5bbb32afc2a76 (patch) | |
tree | 325d1c688970c410fa6e452a84b670fa196ffd1c | |
parent | 7804b5c55888717b35432c2670f4eef23afd583a (diff) | |
download | Nim-a6ba3116b2376d9f3476ef0f8db5bbb32afc2a76.tar.gz |
Fixes for ptr array deref codegen (#11191)
* fixes for ptr array derefence codegen * fix comments, make diff nicer
-rw-r--r-- | compiler/ast.nim | 2 | ||||
-rw-r--r-- | compiler/ccgexprs.nim | 7 | ||||
-rw-r--r-- | compiler/ccgstmts.nim | 49 | ||||
-rw-r--r-- | tests/openarray/tptrarrayderef.nim | 18 |
4 files changed, 36 insertions, 40 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index aeb19ae1a..4ac1a1465 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -768,6 +768,8 @@ type lfHeader, # include header file for symbol lfImportCompilerProc, # ``importc`` of a compilerproc 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 OnUnknown, # location is unknown (stack, heap or static) OnStatic, # in a static section diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 88a69b6a1..d8c9255a7 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -717,8 +717,10 @@ proc isCppRef(p: BProc; typ: PType): bool {.inline.} = skipTypes(typ, abstractInstOwned).kind == tyVar and tfVarIsPtr notin skipTypes(typ, abstractInstOwned).flags -proc genDeref(p: BProc, e: PNode, d: var TLoc; enforceDeref=false) = - let mt = mapType(p.config, e.sons[0].typ) +proc genDeref(p: BProc, e: PNode, d: var TLoc) = + let + enforceDeref = lfEnforceDeref in d.flags + mt = mapType(p.config, e.sons[0].typ) if mt in {ctArray, ctPtrToArray} and not enforceDeref: # XXX the amount of hacks for C's arrays is incredible, maybe we should # 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] initLoc(rec, locExpr, it, d.storage) rec.r = "$1.Field$2" % [rdLoc(d), rope(i)] + rec.flags.incl(lfEnforceDeref) expr(p, it, rec) proc isConstClosure(n: PNode): bool {.inline.} = diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index abddb7c6c..2f8e1653f 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -123,13 +123,13 @@ proc genVarTuple(p: BProc, n: PNode) = if forHcr or isGlobalInBlock: 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.} = if ri.kind in nkCallKinds and (ri.sons[0].kind != nkSym or ri.sons[0].sym.magic == mNone): genAsgnCall(p, le, ri, a) - elif ri.kind in {nkDerefExpr, nkHiddenDeref}: + else: # this is a hacky way to fix #1181 (tmissingderef):: # # 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 # a 'struct' in C to preserve dereferencing semantics completely. Not # worth the effort until version 1.0 is out. - genDeref(p, ri, a, enforceDeref=true) - else: + a.flags.incl(lfEnforceDeref) expr(p, ri, a) proc assignLabel(b: var TBlock): Rope {.inline.} = @@ -597,10 +596,12 @@ proc genWhileStmt(p: BProc, t: PNode) = dec(p.withinLoop) proc genBlock(p: BProc, n: PNode, d: var TLoc) = - # bug #4505: allocate the temp in the outer scope - # so that it can escape the generated {}: - if not isEmptyType(n.typ) and d.k == locNone: - getTemp(p, n.typ, d) + if not isEmptyType(n.typ): + # bug #4505: allocate the temp in the outer scope + # so that it can escape the generated {}: + if d.k == locNone: + getTemp(p, n.typ, d) + d.flags.incl(lfEnforceDeref) preserveBreakIdx: p.breakIdx = startBlock(p) 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) 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) = if e.sons[0].kind == nkSym and sfGoto in e.sons[0].sym.flags: genLineDir(p, e) genGotoVar(p, e.sons[1]) 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 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 discard getTypeDesc(p.module, le.typ.skipTypes(skipPtrs)) - if le.kind in {nkDerefExpr, nkHiddenDeref}: - genDeref(p, le, a, enforceDeref=true) - else: - initLocExpr(p, le, a) + initLoc(a, locNone, le, OnUnknown) + a.flags.incl(lfEnforceDeref) + expr(p, le, a) if fastAsgn: incl(a.flags, lfNoDeepCopy) assert(a.t != nil) genLineDir(p, ri) diff --git a/tests/openarray/tptrarrayderef.nim b/tests/openarray/tptrarrayderef.nim index 5c63f6f98..b75bc08c4 100644 --- a/tests/openarray/tptrarrayderef.nim +++ b/tests/openarray/tptrarrayderef.nim @@ -1,5 +1,8 @@ discard """ - output: "OK" + output: '''[1, 2, 3, 4] +3 +OK +''' """ var @@ -50,4 +53,17 @@ let aa = getFilledBuffer(3) for i in 0..aa[].len-1: 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" |