diff options
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/ccgexprs.nim | 44 | ||||
-rw-r--r-- | compiler/ccgliterals.nim | 18 | ||||
-rw-r--r-- | compiler/ccgtrav.nim | 16 | ||||
-rw-r--r-- | compiler/ccgtypes.nim | 40 | ||||
-rw-r--r-- | compiler/cgen.nim | 4 |
5 files changed, 79 insertions, 43 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index d25a4ad3d..69175fd18 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -256,8 +256,8 @@ proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = # (for objects, etc.): if p.config.selectedGC == gcDestructors: linefmt(p, cpsStmts, - "#nimCopyMem((void*)$1, (NIM_CONST void*)$2, sizeof($3));$n", - addrLoc(p.config, dest), addrLoc(p.config, src), rdLoc(dest)) + "$1.len = $2.len; $1.p = $2.p;$n", + rdLoc(dest), rdLoc(src)) elif needToCopy notin flags or tfShallow in skipTypes(dest.t, abstractVarRange).flags: if dest.storage == OnStack or not usesWriteBarrier(p.config): @@ -1512,28 +1512,19 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) = if op == mHigh: unaryExpr(p, e, d, "($1 ? (#nimCStrLen($1)-1) : -1)") else: unaryExpr(p, e, d, "($1 ? #nimCStrLen($1) : 0)") of tyString: - if not p.module.compileToCpp: - if op == mHigh: unaryExpr(p, e, d, "($1 ? ($1->Sup.len-1) : -1)") - else: unaryExpr(p, e, d, "($1 ? $1->Sup.len : 0)") - else: - if op == mHigh: unaryExpr(p, e, d, "($1 ? ($1->len-1) : -1)") - else: unaryExpr(p, e, d, "($1 ? $1->len : 0)") + var a: TLoc + initLocExpr(p, e.sons[1], a) + var x = lenExpr(p, a) + if op == mHigh: x = "($1-1)" % [x] + putIntoDest(p, d, e, x) of tySequence: + # we go through a temporary here because people write bullshit code. var a, tmp: TLoc initLocExpr(p, e[1], a) getIntTemp(p, tmp) - var frmt: FormatStr - if not p.module.compileToCpp: - if op == mHigh: - frmt = "$1 = ($2 ? ($2->Sup.len-1) : -1);$n" - else: - frmt = "$1 = ($2 ? $2->Sup.len : 0);$n" - else: - if op == mHigh: - frmt = "$1 = ($2 ? ($2->len-1) : -1);$n" - else: - frmt = "$1 = ($2 ? $2->len : 0);$n" - lineCg(p, cpsStmts, frmt, tmp.r, rdLoc(a)) + var x = lenExpr(p, a) + if op == mHigh: x = "($1-1)" % [x] + lineCg(p, cpsStmts, "$1 = $2;$n", tmp.r, x) putIntoDest(p, d, e, tmp.r) of tyArray: # YYY: length(sideeffect) is optimized away incorrectly? @@ -1889,7 +1880,11 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = else: binaryStmt(p, e, d, "$1 = #addChar($1, $2);$n") of mAppendStrStr: genStrAppend(p, e, d) - of mAppendSeqElem: genSeqElemAppend(p, e, d) + of mAppendSeqElem: + if p.config.selectedGc == gcDestructors: + genCall(p, e, d) + else: + genSeqElemAppend(p, e, d) of mEqStr: genStrEquals(p, e, d) of mLeStr: binaryExpr(p, e, d, "(#cmpStrings($1, $2) <= 0)") of mLtStr: binaryExpr(p, e, d, "(#cmpStrings($1, $2) < 0)") @@ -2537,6 +2532,13 @@ proc genConstExpr(p: BProc, n: PNode): Rope = result = genConstSimpleList(p, n) of nkObjConstr: result = genConstObjConstr(p, n) + of nkStrLit..nkTripleStrLit: + if p.config.selectedGc == gcDestructors: + result = genStringLiteralV2Const(p.module, n) + else: + var d: TLoc + initLocExpr(p, n, d) + result = rdLoc(d) else: var d: TLoc initLocExpr(p, n, d) diff --git a/compiler/ccgliterals.nim b/compiler/ccgliterals.nim index a06e4e5d0..34677ec06 100644 --- a/compiler/ccgliterals.nim +++ b/compiler/ccgliterals.nim @@ -54,9 +54,9 @@ proc genStringLiteralV1(m: BModule; n: PNode): Rope = proc genStringLiteralDataOnlyV2(m: BModule, s: string): Rope = result = getTempName(m) addf(m.s[cfsData], "static const struct {$n" & - " NI cap; void* allocator; NIM_CHAR[$2] data;$n" & + " NI cap; void* allocator; NIM_CHAR data[$2];$n" & "} $1 = { $2, NIM_NIL, $3 };$n", - [result, rope(len(s)+1), makeCString(s)]) + [result, rope(len(s)), makeCString(s)]) proc genStringLiteralV2(m: BModule; n: PNode): Rope = let id = nodeTableTestOrSet(m.dataCache, n, m.labels) @@ -67,10 +67,22 @@ proc genStringLiteralV2(m: BModule; n: PNode): Rope = let pureLit = genStringLiteralDataOnlyV2(m, n.strVal) result = getTempName(m) addf(m.s[cfsData], "static const NimStringV2 $1 = {$2, (NimStrPayload*)&$3};$n", - [result, rope(len(n.strVal)+1), pureLit]) + [result, rope(len(n.strVal)), pureLit]) else: result = m.tmpBase & rope(id) +proc genStringLiteralV2Const(m: BModule; n: PNode): Rope = + let id = nodeTableTestOrSet(m.dataCache, n, m.labels) + var pureLit: Rope + if id == m.labels: + discard cgsym(m, "NimStrPayload") + discard cgsym(m, "NimStringV2") + # string literal not found in the cache: + pureLit = genStringLiteralDataOnlyV2(m, n.strVal) + else: + pureLit = m.tmpBase & rope(id) + result = "{$1, (NimStrPayload*)&$2}" % [rope(len(n.strVal)), pureLit] + # ------ Version selector --------------------------------------------------- proc genStringLiteralDataOnly(m: BModule; s: string; info: TLineInfo): Rope = diff --git a/compiler/ccgtrav.nim b/compiler/ccgtrav.nim index 5a6dc8a6e..c69bb2c80 100644 --- a/compiler/ccgtrav.nim +++ b/compiler/ccgtrav.nim @@ -7,8 +7,7 @@ # distribution, for details about the copyright. # -## Generates traversal procs for the C backend. Traversal procs are only an -## optimization; the GC works without them too. +## Generates traversal procs for the C backend. # included from cgen.nim @@ -61,6 +60,7 @@ proc parentObj(accessor: Rope; m: BModule): Rope {.inline.} = else: result = accessor +proc genTraverseProcSeq(c: TTraversalClosure, accessor: Rope, typ: PType) proc genTraverseProc(c: TTraversalClosure, accessor: Rope, typ: PType) = if typ == nil: return @@ -93,8 +93,18 @@ proc genTraverseProc(c: TTraversalClosure, accessor: Rope, typ: PType) = let typ = getUniqueType(typ) for i in countup(0, sonsLen(typ) - 1): genTraverseProc(c, ropecg(c.p.module, "$1.Field$2", accessor, i.rope), typ.sons[i]) - of tyRef, tyString, tySequence: + of tyRef: lineCg(p, cpsStmts, c.visitorFrmt, accessor) + of tySequence: + if tfHasAsgn notin typ.flags: + lineCg(p, cpsStmts, c.visitorFrmt, accessor) + elif containsGarbageCollectedRef(typ.lastSon): + # destructor based seqs are themselves not traced but their data is, if + # they contain a GC'ed type: + genTraverseProcSeq(c, accessor, typ) + of tyString: + if tfHasAsgn notin typ.flags: + lineCg(p, cpsStmts, c.visitorFrmt, accessor) of tyProc: if typ.callConv == ccClosure: lineCg(p, cpsStmts, c.visitorFrmt, ropecg(c.p.module, "$1.ClE_0", accessor)) diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index b83c96660..59fbfc3e1 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -359,8 +359,11 @@ proc getTypeDescWeak(m: BModule; t: PType; check: var IntSet): Rope = result = getTypeForward(m, t, hashType(t)) pushType(m, t) of tySequence: - result = getTypeForward(m, t, hashType(t)) & seqStar(m) - pushType(m, t) + if m.config.selectedGC == gcDestructors: + result = getTypeDescAux(m, t, check) + else: + result = getTypeForward(m, t, hashType(t)) & seqStar(m) + pushType(m, t) else: result = getTypeDescAux(m, t, check) @@ -491,7 +494,7 @@ proc genRecordFieldsAux(m: BModule, n: PNode, if fieldType.kind == tyArray and tfUncheckedArray in fieldType.flags: addf(result, "$1 $2[SEQ_DECL_SIZE];$n", [getTypeDescAux(m, fieldType.elemType, check), sname]) - elif fieldType.kind == tySequence: + elif fieldType.kind == tySequence and m.config.selectedGC != gcDestructors: # we need to use a weak dependency here for trecursive_table. addf(result, "$1 $2;$n", [getTypeDescWeak(m, field.loc.t, check), sname]) elif field.bitsize != 0: @@ -606,12 +609,13 @@ proc resolveStarsInCppType(typ: PType, idx, stars: int): PType = else: result.elemType proc getSeqPayloadType(m: BModule; t: PType): Rope = - var check = initIntSet() - result = getTypeForward(m, t, hashType(t)) - # XXX remove this duplication: - appcg(m, m.s[cfsSeqTypes], - "struct $2_Content { NI cap; void* allocator; $1 data[SEQ_DECL_SIZE];$n } ", - [getTypeDescAux(m, t.sons[0], check), result]) + result = getTyppan class="o">=bottom> <br> <font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr> <tr><td bgcolor="#aa55cc"><tt> </tt></td><td> </td> <td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="curses.html">curses</a><br> </td><td width="25%" valign=top><a href="ranger.gui.ui.html">ranger.gui.ui</a><br> </td><td width="25%" valign=top><a href="unittest.html">unittest</a><br> </td><td width="25%" valign=top></td></tr></table></td></tr></table><p> <table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section"> <tr bgcolor="#ee77aa"> <td colspan=3 valign=bottom> <br> <font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr> <tr><td bgcolor="#ee77aa"><tt> </tt></td><td> </td> <td width="100%"><dl> <dt><font face="helvetica, arial"><a href="unittest.html#TestCase">unittest.TestCase</a>(<a href="__builtin__.html#object">__builtin__.object</a>) </font></dt><dd> <dl> <dt><font face="helvetica, arial"><a href="test.tc_ui.html#Test">Test</a> </font></dt></dl> </dd> </dl> <p> <table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section"> <tr bgcolor="#ffc8d8"> <td colspan=3 valign=bottom> <br> <font color="#000000" face="helvetica, arial"><a name="Test">class <strong>Test</strong></a>(<a href="unittest.html#TestCase">unittest.TestCase</a>)</font></td></tr> <tr><td bgcolor="#ffc8d8"><tt> </tt></td><td> </td> <td width="100%"><dl><dt>Method resolution order:</dt> <dd><a href="test.tc_ui.html#Test">Test</a></dd> <dd><a href="unittest.html#TestCase">unittest.TestCase</a></dd> <dd><a href="__builtin__.html#object">__builtin__.object</a></dd> </dl> <hr> Methods defined here:<br> <dl><dt><a name="Test-setUp"><strong>setUp</strong></a>(self)</dt></dl> <dl><dt><a name="Test-tearDown"><strong>tearDown</strong></a>(self)</dt></dl> <dl><dt><a name="Test-test_passing"><strong>test_passing</strong></a>(self)</dt></dl> <hr> Methods inherited from <a href="unittest.html#TestCase">unittest.TestCase</a>:<br> <dl><dt><a name="Test-__call__"><strong>__call__</strong></a>(self, *args, **kwds)</dt></dl> <dl><dt><a name="Test-__eq__"><strong>__eq__</strong></a>(self, other)</dt></dl> <dl><dt><a name="Test-__hash__"><strong>__hash__</strong></a>(self)</dt></dl> <dl><dt><a name="Test-__init__"><strong>__init__</strong></a>(self, methodName<font color="#909090">='runTest'</font>)</dt><dd><tt>Create an instance of the class that will use the named test<br> method when executed. Raises a ValueError if the instance does<br> not have a method with the specified name.</tt></dd></dl> <dl><dt><a name="Test-__ne__"><strong>__ne__</strong></a>(self, other)</dt></dl> <dl><dt><a name="Test-__repr__"><strong>__repr__</strong></a>(self)</dt></dl> <dl><dt><a name="Test-__str__"><strong>__str__</strong></a>(self)</dt></dl> <dl><dt><a name="Test-assertAlmostEqual"><strong>assertAlmostEqual</strong></a> = failUnlessAlmostEqual(self, first, second, places<font color="#909090">=7</font>, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail if the two objects are unequal as determined by their<br> difference rounded to the given number of decimal places<br> (default 7) and comparing to zero.<br> <br> Note that decimal places (from zero) are usually not the same<br> as significant digits (measured from the most signficant digit).</tt></dd></dl> <dl><dt><a name="Test-assertAlmostEquals"><strong>assertAlmostEquals</strong></a> = failUnlessAlmostEqual(self, first, second, places<font color="#909090">=7</font>, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail if the two objects are unequal as determined by their<br> difference rounded to the given number of decimal places<br> (default 7) and comparing to zero.<br> <br> Note that decimal places (from zero) are usually not the same<br> as significant digits (measured from the most signficant digit).</tt></dd></dl> <dl><dt><a name="Test-assertEqual"><strong>assertEqual</strong></a> = failUnlessEqual(self, first, second, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail if the two objects are unequal as determined by the '=='<br> operator.</tt></dd></dl> <dl><dt><a name="Test-assertEquals"><strong>assertEquals</strong></a> = failUnlessEqual(self, first, second, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail if the two objects are unequal as determined by the '=='<br> operator.</tt></dd></dl> <dl><dt><a name="Test-assertFalse"><strong>assertFalse</strong></a> = failIf(self, expr, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail the test if the expression is true.</tt></dd></dl> <dl><dt><a name="Test-assertNotAlmostEqual"><strong>assertNotAlmostEqual</strong></a> = failIfAlmostEqual(self, first, second, places<font color="#909090">=7</font>, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail if the two objects are equal as determined by their<br> difference rounded to the given number of decimal places<br> (default 7) and comparing to zero.<br> <br> Note that decimal places (from zero) are usually not the same<br> as significant digits (measured from the most signficant digit).</tt></dd></dl> <dl><dt><a name="Test-assertNotAlmostEquals"><strong>assertNotAlmostEquals</strong></a> = failIfAlmostEqual(self, first, second, places<font color="#909090">=7</font>, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail if the two objects are equal as determined by their<br> difference rounded to the given number of decimal places<br> (default 7) and comparing to zero.<br> <br> Note that decimal places (from zero) are usually not the same<br> as significant digits (measured from the most signficant digit).</tt></dd></dl> <dl><dt><a name="Test-assertNotEqual"><strong>assertNotEqual</strong></a> = failIfEqual(self, first, second, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail if the two objects are equal as determined by the '=='<br> operator.</tt></dd></dl> <dl><dt><a name="Test-assertNotEquals"><strong>assertNotEquals</strong></a> = failIfEqual(self, first, second, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail if the two objects are equal as determined by the '=='<br> operator.</tt></dd></dl> <dl><dt><a name="Test-assertRaises"><strong>assertRaises</strong></a> = failUnlessRaises(self, excClass, callableObj, *args, **kwargs)</dt><dd><tt>Fail unless an exception of class excClass is thrown<br> by callableObj when invoked with arguments args and keyword<br> arguments kwargs. If a different type of exception is<br> thrown, it will not be caught, and the test case will be<br> deemed to have suffered an error, exactly as for an<br> unexpected exception.</tt></dd></dl> <dl><dt><a name="Test-assertTrue"><strong>assertTrue</strong></a> = failUnless(self, expr, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail the test unless the expression is true.</tt></dd></dl> <dl><dt><a name="Test-assert_"><strong>assert_</strong></a> = failUnless(self, expr, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail the test unless the expression is true.</tt></dd></dl> <dl><dt><a name="Test-countTestCases"><strong>countTestCases</strong></a>(self)</dt></dl> <dl><dt><a name="Test-debug"><strong>debug</strong></a>(self)</dt><dd><tt>Run the test without collecting errors in a TestResult</tt></dd></dl> <dl><dt><a name="Test-defaultTestResult"><strong>defaultTestResult</strong></a>(self)</dt></dl> <dl><dt><a name="Test-fail"><strong>fail</strong></a>(self, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail immediately, with the given message.</tt></dd></dl> <dl><dt><a name="Test-failIf"><strong>failIf</strong></a>(self, expr, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail the test if the expression is true.</tt></dd></dl> <dl><dt><a name="Test-failIfAlmostEqual"><strong>failIfAlmostEqual</strong></a>(self, first, second, places<font color="#909090">=7</font>, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail if the two objects are equal as determined by their<br> difference rounded to the given number of decimal places<br> (default 7) and comparing to zero.<br> <br> Note that decimal places (from zero) are usually not the same<br> as significant digits (measured from the most signficant digit).</tt></dd></dl> <dl><dt><a name="Test-failIfEqual"><strong>failIfEqual</strong></a>(self, first, second, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail if the two objects are equal as determined by the '=='<br> operator.</tt></dd></dl> <dl><dt><a name="Test-failUnless"><strong>failUnless</strong></a>(self, expr, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail the test unless the expression is true.</tt></dd></dl> <dl><dt><a name="Test-failUnlessAlmostEqual"><strong>failUnlessAlmostEqual</strong></a>(self, first, second, places<font color="#909090">=7</font>, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail if the two objects are unequal as determined by their<br> difference rounded to the given number of decimal places<br> (default 7) and comparing to zero.<br> <br> Note that decimal places (from zero) are usually not the same<br> as significant digits (measured from the most signficant digit).</tt></dd></dl> <dl><dt><a name="Test-failUnlessEqual"><strong>failUnlessEqual</strong></a>(self, first, second, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail if the two objects are unequal as determined by the '=='<br> operator.</tt></dd></dl> <dl><dt><a name="Test-failUnlessRaises"><strong>failUnlessRaises</strong></a>(self, excClass, callableObj, *args, **kwargs)</dt><dd><tt>Fail unless an exception of class excClass is thrown<br> by callableObj when invoked with arguments args and keyword<br> arguments kwargs. If a different type of exception is<br> thrown, it will not be caught, and the test case will be<br> deemed to have suffered an error, exactly as for an<br> unexpected exception.</tt></dd></dl> <dl><dt><a name="Test-id"><strong>id</strong></a>(self)</dt></dl> <dl><dt><a name="Test-run"><strong>run</strong></a>(self, result<font color="#909090">=None</font>)</dt></dl> <dl><dt><a name="Test-shortDescription"><strong>shortDescription</strong></a>(self)</dt><dd><tt>Returns a one-line description of the test, or None if no<br> description has been provided.<br> <br> The default implementation of this method returns the first line of<br> the specified test method's docstring.</tt></dd></dl> <hr> Data descriptors inherited from <a href="unittest.html#TestCase">unittest.TestCase</a>:<br> <dl><dt><strong>__dict__</strong></dt> <dd><tt>dictionary for instance variables (if defined)</tt></dd> </dl> <dl><dt><strong>__weakref__</strong></dt> <dd><tt>list of weak references to the object (if defined)</tt></dd> </dl> <hr> Data and other attributes inherited from <a href="unittest.html#TestCase">unittest.TestCase</a>:<br> <dl><dt><strong>failureException</strong> = <type 'exceptions.AssertionError'><dd><tt>Assertion failed.</tt></dl> </td></tr></table></td></tr></table> </body></html> |