diff --git a/Changes b/Changes index 59a28b030..f96cdbee3 100644 --- a/Changes +++ b/Changes @@ -15,6 +15,8 @@ The contributors that suggested a given feature are shown in []. Thanks! *** Add new reloop optimization for repetitive assignment compression. +*** Support string.atoi and similar methods, bug1289. [Joel Holdsworth] + **** Fix internals to be C++ null-pointer-check clean. **** Fix internals to avoid 'using namespace std'. diff --git a/src/V3Width.cpp b/src/V3Width.cpp index d16168303..97caa4cbb 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -1599,7 +1599,7 @@ private: 0, selwidth)); nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep); } else { - nodep->v3error("Unknown built-in enum method '"<fromp()->prettyTypeName()<<"'"); + nodep->v3error("Unknown built-in enum method '"<prettyName()<<"'"); } } else if (AstUnpackArrayDType* arrayType = VN_CAST(fromDtp, UnpackArrayDType)) { @@ -1638,18 +1638,29 @@ private: nodep->deleteTree(); VL_DANGLING(nodep); } else { - nodep->v3error("Unknown built-in array method '"<fromp()->prettyTypeName()<<"'"); + nodep->v3error("Unknown built-in array method '"<prettyName()<<"'"); } } else if (basicp && basicp->isString()) { // Method call on string if (nodep->name() == "len") { // Constant value + if (nodep->pinsp()) nodep->v3error("Arguments passed to string.len method, but it does not take arguments"); AstNode* newp = new AstLenN(nodep->fileline(), nodep->fromp()->unlinkFrBack()); nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep); + } else if (nodep->name() == "itoa") { + replaceWithSFormat(nodep, "%0d"); VL_DANGLING(nodep); + } else if (nodep->name() == "hextoa") { + replaceWithSFormat(nodep, "%0x"); VL_DANGLING(nodep); + } else if (nodep->name() == "octtoa") { + replaceWithSFormat(nodep, "%0o"); VL_DANGLING(nodep); + } else if (nodep->name() == "bintoa") { + replaceWithSFormat(nodep, "%0b"); VL_DANGLING(nodep); + } else if (nodep->name() == "realtoa") { + replaceWithSFormat(nodep, "%g"); VL_DANGLING(nodep); } else { - nodep->v3error("Unsupported: built-in string method '"<fromp()->prettyTypeName()<<"'"); + nodep->v3error("Unsupported: built-in string method '"<prettyName()<<"'"); } } else { @@ -3505,6 +3516,26 @@ private: return newp; } + //---------------------------------------------------------------------- + // METHODS - strings + + void replaceWithSFormat(AstMethodSel* nodep, const string& format) { + // For string.itoa and similar, replace with SFormatF + AstArg* argp = VN_CAST(nodep->pinsp(), Arg); + if (!argp) { + nodep->v3error("Argument needed for string." + +nodep->prettyName()+" method"); + return; + } + AstNodeVarRef* fromp = VN_CAST(nodep->fromp()->unlinkFrBack(), VarRef); + AstNode* newp = new AstAssign(nodep->fileline(), fromp, + new AstSFormatF(nodep->fileline(), format, false, + argp->exprp()->unlinkFrBack())); + fromp->lvalue(true); + nodep->replaceWith(newp); + pushDeletep(nodep); VL_DANGLING(nodep); + } + //---------------------------------------------------------------------- // METHODS - data types diff --git a/test_regress/t/t_string_type_methods.v b/test_regress/t/t_string_type_methods.v index 03e5ca566..fb71cb06e 100644 --- a/test_regress/t/t_string_type_methods.v +++ b/test_regress/t/t_string_type_methods.v @@ -36,12 +36,12 @@ module t (/*AUTOARG*/ s="101"; `checkh(s.atooct(), 'o101); s="101"; `checkh(s.atobin(), 'b101); s="1.23"; `checkg(s.atoreal(), 1.23); +`endif s.itoa(123); `checks(s, "123"); s.hextoa(123); `checks(s, "7b"); s.octtoa(123); `checks(s, "173"); s.bintoa(123); `checks(s, "1111011"); s.realtoa(1.23); `checks(s, "1.23"); -`endif end // Check runtime @@ -53,15 +53,17 @@ module t (/*AUTOARG*/ end else if (cyc==1) begin `checkh(s.len(),4); + end `ifndef VERILATOR + else if (cyc==2) begin s.putc(2, "z"); end - else if (cyc==2) begin + else if (cyc==3) begin `checks(s, "12z4"); `checkh(s.getc(2), "z"); s="abCD"; end - else if (cyc==3) begin + else if (cyc==4) begin `checks(s.toupper(), "ABCD"); `checks(s.tolower(), "abcd"); s="b"; @@ -84,6 +86,9 @@ module t (/*AUTOARG*/ end else if (cyc==8) begin `checkg(s.atoreal(), 1.23); + end +`endif + else if (cyc==9) begin s.itoa(123); end else if (cyc==10) begin @@ -104,7 +109,6 @@ module t (/*AUTOARG*/ end else if (cyc==14) begin `checks(s, "1.23"); -`endif end else if (cyc==99) begin $write("*-* All Finished *-*\n");