From 37cc9b2226fc422561700dd1197450106db2b7c5 Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 13 Nov 2014 19:07:27 +0100 Subject: fixes #1181 --- compiler/ccgexprs.nim | 60 +++++++++++++++++++++------------------ compiler/ccgstmts.nim | 11 +++++++ compiler/cgen.nim | 2 -- lib/pure/osproc.nim | 6 ++-- tests/ccg/tmissingbracket.nim | 52 --------------------------------- tests/ccgbugs/tmissingbracket.nim | 52 +++++++++++++++++++++++++++++++++ 6 files changed, 98 insertions(+), 85 deletions(-) delete mode 100644 tests/ccg/tmissingbracket.nim create mode 100644 tests/ccgbugs/tmissingbracket.nim diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index b6feb78b2..b91c54e8b 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -655,13 +655,15 @@ proc unaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) = ropef(unArithTab[op], [rdLoc(a), toRope(getSize(t) * 8), getSimpleTypeDesc(p.module, e.typ)])) -proc genDeref(p: BProc, e: PNode, d: var TLoc) = - var a: TLoc - if mapType(e.sons[0].typ) in {ctArray, ctPtrToArray}: +proc genDeref(p: BProc, e: PNode, d: var TLoc; enforceDeref=false) = + if mapType(e.sons[0].typ) 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? + #if e[0].kind != nkBracketExpr: + # message(e.info, warnUser, "CAME HERE " & renderTree(e)) expr(p, e.sons[0], d) else: + var a: TLoc initLocExpr(p, e.sons[0], a) case skipTypes(a.t, abstractInst).kind of tyRef: @@ -794,15 +796,15 @@ proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) = else: genRecordField(p, e.sons[0], d) -proc genArrayElem(p: BProc, e: PNode, d: var TLoc) = +proc genArrayElem(p: BProc, x, y: PNode, d: var TLoc) = var a, b: TLoc - initLocExpr(p, e.sons[0], a) - initLocExpr(p, e.sons[1], b) + initLocExpr(p, x, a) + initLocExpr(p, y, b) var ty = skipTypes(skipTypes(a.t, abstractVarRange), abstractPtrs) var first = intLiteral(firstOrd(ty)) # emit range check: if optBoundsCheck in p.options and tfUncheckedArray notin ty.flags: - if not isConstExpr(e.sons[1]): + if not isConstExpr(y): # semantic pass has already checked for const index expressions if firstOrd(ty) == 0: if (firstOrd(b.t) < firstOrd(ty)) or (lastOrd(b.t) > lastOrd(ty)): @@ -812,26 +814,26 @@ proc genArrayElem(p: BProc, e: PNode, d: var TLoc) = linefmt(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseIndexError();$n", rdCharLoc(b), first, intLiteral(lastOrd(ty))) else: - let idx = getOrdValue(e.sons[1]) + let idx = getOrdValue(y) if idx < firstOrd(ty) or idx > lastOrd(ty): - localError(e.info, errIndexOutOfBounds) + localError(x.info, errIndexOutOfBounds) d.inheritLocation(a) putIntoDest(p, d, elemType(skipTypes(ty, abstractVar)), rfmt(nil, "$1[($2)- $3]", rdLoc(a), rdCharLoc(b), first)) -proc genCStringElem(p: BProc, e: PNode, d: var TLoc) = +proc genCStringElem(p: BProc, x, y: PNode, d: var TLoc) = var a, b: TLoc - initLocExpr(p, e.sons[0], a) - initLocExpr(p, e.sons[1], b) + initLocExpr(p, x, a) + initLocExpr(p, y, b) var ty = skipTypes(a.t, abstractVarRange) if d.k == locNone: d.s = a.s putIntoDest(p, d, elemType(skipTypes(ty, abstractVar)), rfmt(nil, "$1[$2]", rdLoc(a), rdCharLoc(b))) -proc genOpenArrayElem(p: BProc, e: PNode, d: var TLoc) = +proc genOpenArrayElem(p: BProc, x, y: PNode, d: var TLoc) = var a, b: TLoc - initLocExpr(p, e.sons[0], a) - initLocExpr(p, e.sons[1], b) # emit range check: + initLocExpr(p, x, a) + initLocExpr(p, y, b) # emit range check: if optBoundsCheck in p.options: linefmt(p, cpsStmts, "if ((NU)($1) >= (NU)($2Len0)) #raiseIndexError();$n", rdLoc(b), rdLoc(a)) # BUGFIX: ``>=`` and not ``>``! @@ -839,10 +841,10 @@ proc genOpenArrayElem(p: BProc, e: PNode, d: var TLoc) = putIntoDest(p, d, elemType(skipTypes(a.t, abstractVar)), rfmt(nil, "$1[$2]", rdLoc(a), rdCharLoc(b))) -proc genSeqElem(p: BProc, e: PNode, d: var TLoc) = +proc genSeqElem(p: BProc, x, y: PNode, d: var TLoc) = var a, b: TLoc - initLocExpr(p, e.sons[0], a) - initLocExpr(p, e.sons[1], b) + initLocExpr(p, x, a) + initLocExpr(p, y, b) var ty = skipTypes(a.t, abstractVarRange) if ty.kind in {tyRef, tyPtr}: ty = skipTypes(ty.lastSon, abstractVarRange) # emit range check: @@ -862,6 +864,17 @@ proc genSeqElem(p: BProc, e: PNode, d: var TLoc) = putIntoDest(p, d, elemType(skipTypes(a.t, abstractVar)), rfmt(nil, "$1->data[$2]", rdLoc(a), rdCharLoc(b))) +proc genBracketExpr(p: BProc; n: PNode; d: var TLoc) = + var ty = skipTypes(n.sons[0].typ, abstractVarRange) + if ty.kind in {tyRef, tyPtr}: ty = skipTypes(ty.lastSon, abstractVarRange) + case ty.kind + of tyArray, tyArrayConstr: genArrayElem(p, n.sons[0], n.sons[1], d) + of tyOpenArray, tyVarargs: genOpenArrayElem(p, n.sons[0], n.sons[1], d) + of tySequence, tyString: genSeqElem(p, n.sons[0], n.sons[1], d) + of tyCString: genCStringElem(p, n.sons[0], n.sons[1], d) + of tyTuple: genTupleElem(p, n, d) + else: internalError(n.info, "expr(nkBracketExpr, " & $ty.kind & ')') + proc genAndOr(p: BProc, e: PNode, d: var TLoc, m: TMagic) = # how to generate code? # 'expr1 and expr2' becomes: @@ -1985,16 +1998,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) = of nkCast: genCast(p, n, d) of nkHiddenStdConv, nkHiddenSubConv, nkConv: genConv(p, n, d) of nkHiddenAddr, nkAddr: genAddr(p, n, d) - of nkBracketExpr: - var ty = skipTypes(n.sons[0].typ, abstractVarRange) - if ty.kind in {tyRef, tyPtr}: ty = skipTypes(ty.lastSon, abstractVarRange) - case ty.kind - of tyArray, tyArrayConstr: genArrayElem(p, n, d) - of tyOpenArray, tyVarargs: genOpenArrayElem(p, n, d) - of tySequence, tyString: genSeqElem(p, n, d) - of tyCString: genCStringElem(p, n, d) - of tyTuple: genTupleElem(p, n, d) - else: internalError(n.info, "expr(nkBracketExpr, " & $ty.kind & ')') + of nkBracketExpr: genBracketExpr(p, n, d) of nkDerefExpr, nkHiddenDeref: genDeref(p, n, d) of nkDotExpr: genRecordField(p, n, d) of nkCheckedFieldExpr: genCheckedRecordField(p, n, d) diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 0898f0b03..e5848f558 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -68,10 +68,21 @@ proc genVarTuple(p: BProc, n: PNode) = [rdLoc(tup), mangleRecFieldName(t.n.sons[i].sym, t)]) putLocIntoDest(p, v.loc, field) +proc genDeref(p: BProc, e: PNode, d: var TLoc; enforceDeref=false) + 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}: + # this is a hacky way to fix #1181 (tmissingderef):: + # + # var arr1 = cast[ptr array[4, int8]](addr foo)[] + # + # 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: expr(p, ri, a) diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 9e353f0ea..112203ef1 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -55,7 +55,6 @@ proc initLoc(result: var TLoc, k: TLocKind, typ: PType, s: TStorageLoc) = result.s = s result.t = getUniqueType(typ) result.r = nil - #result.a = - 1 result.flags = {} proc fillLoc(a: var TLoc, k: TLocKind, typ: PType, r: PRope, s: TStorageLoc) = @@ -63,7 +62,6 @@ proc fillLoc(a: var TLoc, k: TLocKind, typ: PType, r: PRope, s: TStorageLoc) = if a.k == locNone: a.k = k a.t = getUniqueType(typ) - #a.a = - 1 a.s = s if a.r == nil: a.r = r diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim index 3963497fd..2983712c8 100644 --- a/lib/pure/osproc.nim +++ b/lib/pure/osproc.nim @@ -495,10 +495,10 @@ when defined(Windows) and not defined(useNimRtl): if running(p): discard terminateProcess(p.fProcessHandle, 0) - proc kill(p: PProcess) = + proc kill(p: Process) = terminate(p) - - proc waitForExit(p: PProcess, timeout: int = -1): int = + + proc waitForExit(p: Process, timeout: int = -1): int = discard waitForSingleObject(p.fProcessHandle, timeout.int32) var res: int32 diff --git a/tests/ccg/tmissingbracket.nim b/tests/ccg/tmissingbracket.nim deleted file mode 100644 index ba681ebda..000000000 --- a/tests/ccg/tmissingbracket.nim +++ /dev/null @@ -1,52 +0,0 @@ -discard """ - output: '''Subobject test called -5''' -""" - -type - TClassOfTCustomObject {.pure, inheritable.} = object - base* : ptr TClassOfTCustomObject - className* : string - TClassOfTobj = object of TClassOfTCustomObject - nil - TCustomObject = ref object {.inheritable.} - class* : ptr TClassOfTCustomObject - TObj = ref object of TCustomObject - data: int - -var ClassOfTObj: TClassOfTObj - -proc initClassOfTObj() = - ClassOfTObj.base = nil - ClassOfTObj.className = "TObj" - -initClassOfTObj() - -proc initialize*(self: TObj) = - self.class = addr ClassOfTObj - # this generates wrong C code: && instead of & - -proc newInstance(T: typedesc): T = - mixin initialize - new(result) - initialize(result) - -var o = TObj.newInstance() - -type - TestObj* = object of TObject - t:int - SubObject* = object of TestObj - -method test*(t:var TestObj) = - echo "test called" - -method test*(t:var SubObject) = - echo "Subobject test called" - t.t= 5 - -var a: SubObject - -a.test() -echo a.t - diff --git a/tests/ccgbugs/tmissingbracket.nim b/tests/ccgbugs/tmissingbracket.nim new file mode 100644 index 000000000..ba681ebda --- /dev/null +++ b/tests/ccgbugs/tmissingbracket.nim @@ -0,0 +1,52 @@ +discard """ + output: '''Subobject test called +5''' +""" + +type + TClassOfTCustomObject {.pure, inheritable.} = object + base* : ptr TClassOfTCustomObject + className* : string + TClassOfTobj = object of TClassOfTCustomObject + nil + TCustomObject = ref object {.inheritable.} + class* : ptr TClassOfTCustomObject + TObj = ref object of TCustomObject + data: int + +var ClassOfTObj: TClassOfTObj + +proc initClassOfTObj() = + ClassOfTObj.base = nil + ClassOfTObj.className = "TObj" + +initClassOfTObj() + +proc initialize*(self: TObj) = + self.class = addr ClassOfTObj + # this generates wrong C code: && instead of & + +proc newInstance(T: typedesc): T = + mixin initialize + new(result) + initialize(result) + +var o = TObj.newInstance() + +type + TestObj* = object of TObject + t:int + SubObject* = object of TestObj + +method test*(t:var TestObj) = + echo "test called" + +method test*(t:var SubObject) = + echo "Subobject test called" + t.t= 5 + +var a: SubObject + +a.test() +echo a.t + -- cgit 1.4.1-2-gfad0