changeset 1102:ae950bd712d3

Use stringstream in asm generation instead of OutBuffer. Besides looking better, this should reduce allocations and copying.
author Frits van Bommel <fvbommel wxs.nl>
date Thu, 12 Mar 2009 14:08:57 +0100
parents 8bf8b058944a
children b30fe7e1dbb9
files gen/asm-x86-32.h gen/asm-x86-64.h gen/asmstmt.cpp
diffstat 3 files changed, 99 insertions(+), 127 deletions(-) [+]
line wrap: on
line diff
--- a/gen/asm-x86-32.h	Thu Mar 12 14:08:57 2009 +0100
+++ b/gen/asm-x86-32.h	Thu Mar 12 14:08:57 2009 +0100
@@ -1206,7 +1206,7 @@
         Scope * sc;
 
         Token * token;
-        OutBuffer * insnTemplate;
+        std::ostringstream insnTemplate;
 
         AsmOp       op;
         AsmOpInfo * opInfo;
@@ -1219,7 +1219,6 @@
             this->sc = sc;
             this->stmt = stmt;
             token = stmt->tokens;
-            insnTemplate = new OutBuffer;
 
             opInfo = NULL;
 
@@ -1450,8 +1449,7 @@
         void setAsmCode()
         {
             AsmCode * asmcode = new AsmCode ( N_Regs );
-            asmcode->insnTemplateLen = insnTemplate->offset;
-            asmcode->insnTemplate = ( char* ) insnTemplate->extractData();
+            asmcode->insnTemplate = insnTemplate.str();
             stmt->asmcode = ( code* ) asmcode;
         }
 
@@ -1513,9 +1511,9 @@
                 {
                     case Arg_Integer:
                         if ( e->type->isunsigned() )
-                            insnTemplate->printf ( "$%llu", e->toUInteger() );
+                            insnTemplate << "$" << e->toUInteger();
                         else
-                            insnTemplate->printf ( "$%lld", e->toInteger() );
+                            insnTemplate << "$" << e->toInteger();
                         break;
 
                     case Arg_Pointer:
@@ -1536,10 +1534,10 @@
 
                                 // osx needs an extra underscore
                                 if ( global.params.os == OSMacOSX )
-                                    insnTemplate->writestring ( "_" );
+                                    insnTemplate << "_";
 
                                 // print out the mangle
-                                insnTemplate->writestring ( vd->mangle() );
+                                insnTemplate << vd->mangle();
                                 vd->nakedUse = true;
                                 break;
                             }
@@ -1554,25 +1552,23 @@
             }
             else
             {
-                insnTemplate->writestring ( ( char* ) fmt );
-                insnTemplate->printf ( "<<%s%d>>", ( mode==Mode_Input ) ?"in":"out", asmcode->args.size() );
+                insnTemplate << fmt
+                             << "<<" << (mode==Mode_Input ? "in" : "out") << asmcode->args.size() << ">>";
                 asmcode->args.push_back ( AsmArg ( type, e, mode ) );
             }
         }
         void addOperand2 ( const char * fmtpre, const char * fmtpost, AsmArgType type, Expression * e, AsmCode * asmcode, AsmArgMode mode = Mode_Input )
         {
             assert ( !sc->func->naked );
-            insnTemplate->writestring ( ( char* ) fmtpre );
-            insnTemplate->printf ( "<<%s%d>>", ( mode==Mode_Input ) ?"in":"out", asmcode->args.size() );
-            insnTemplate->writestring ( ( char* ) fmtpost );
+            insnTemplate << fmtpre
+                         << "<<" << (mode==Mode_Input ? "in" : "out") << ">>"
+                         << fmtpost;
             asmcode->args.push_back ( AsmArg ( type, e, mode ) );
         }
 
         void addLabel ( char* id )
         {
-            insnTemplate->writestring ( sc->func->mangle() );
-            insnTemplate->writestring ( "_" );
-            insnTemplate->writestring ( id );
+            insnTemplate << sc->func->mangle() <<  "_" << id;
         }
 
         /* Determines whether the operand is a register, memory reference
@@ -1653,8 +1649,7 @@
 
         void writeReg ( Reg reg )
         {
-            insnTemplate->writestring ( ( char* ) "%" );
-            insnTemplate->write ( regInfo[reg].gccName.c_str(), regInfo[reg].gccName.length() );
+            insnTemplate << "%" << regInfo[reg].gccName;
         }
 
         bool opTakesLabel()
@@ -1726,7 +1721,7 @@
             bool use_star;
             AsmArgMode mode;
 
-            insnTemplate = new OutBuffer;
+            insnTemplate.str("");
             // %% todo: special case for something..
             if ( opInfo->linkType == Out_Mnemonic )
                 mnemonic = alternateMnemonics[opInfo->link];
@@ -1795,7 +1790,7 @@
             else if ( op == Op_Branch )
             {
                 if ( operands[0].dataSize == Far_Ptr ) // %% type=Far_Ptr not set by Seg:Ofss OTOH, we don't support that..
-                    insnTemplate->writebyte ( 'l' );
+                    insnTemplate << 'l';
             }
             else if ( op == Op_fxch || op == Op_FfdRR_P || op == Op_FidR_P )
             {
@@ -1837,11 +1832,10 @@
                 {
                     int mlen = strlen ( mnemonic );
                     if ( mnemonic[mlen-1] == 'd' )
-                        insnTemplate->write ( mnemonic, mlen-1 );
+                        insnTemplate.write(mnemonic, mlen-1);
                     else
                     {
-                        insnTemplate->writestring ( ( char* ) mnemonic );
-                        insnTemplate->writebyte ( 'w' );
+                        insnTemplate << mnemonic << 'w';
                     }
                 }
                 break;
@@ -1856,12 +1850,11 @@
                     int mlen = strlen ( mnemonic );
                     if ( mnemonic[mlen-1] == 'd' )
                     {
-                        insnTemplate->write ( mnemonic, mlen-1 );
-                        insnTemplate->writebyte ( 'l' );
+                        insnTemplate.write(mnemonic, mlen-1) << 'l';
                     }
                     else
                     {
-                        insnTemplate->writestring ( ( char* ) mnemonic );
+                        insnTemplate << mnemonic;
                     }
                 }
                 break;
@@ -1888,15 +1881,13 @@
                             return false;
                     }
                     assert ( type_char != 0 );
-                    insnTemplate->write ( mnemonic, mlen-1 );
-                    insnTemplate->writebyte ( tc_1 );
-                    insnTemplate->writebyte ( type_char );
+                    insnTemplate.write(mnemonic, mlen-1) << tc_1 << type_char;
                 }
                 break;
                 default:
-                    insnTemplate->writestring ( ( char* ) mnemonic );
+                    insnTemplate << mnemonic;
                     if ( type_char )
-                        insnTemplate->writebyte ( type_char );
+                        insnTemplate << type_char;
                     break;
             }
 
@@ -1950,12 +1941,12 @@
                 asmcode->regs[Reg_EDX] = true;
             }
 
-            insnTemplate->writebyte ( ' ' );
+            insnTemplate << ' ';
             for ( int i__ = 0; i__ < nOperands; i__++ )
             {
                 int i;
                 if ( i__ != 0 )
-                    insnTemplate->writestring ( ( char* ) ", " );
+                    insnTemplate << ", ";
 
                 fmt = "$";
 
@@ -2003,7 +1994,7 @@
                             addOperand ( "$", Arg_LocalSize,
                                          ( Expression * ) operand->symbolDisplacement.data[0], asmcode );
                             if ( operand->constDisplacement )
-                                insnTemplate->writebyte ( '+' );
+                                insnTemplate << '+';
                             else
                                 break;
                         }
@@ -2016,7 +2007,7 @@
                                          asmcode );
 
                             if ( operand->constDisplacement )
-                                insnTemplate->writebyte ( '+' );
+                                insnTemplate << '+';
                             else
                                 // skip the addOperand(fmt, Arg_Integer...) below
                                 break;
@@ -2033,11 +2024,11 @@
                             }
                         }
                         if ( opTakesLabel() /*opInfo->takesLabel()*/ )
-                            insnTemplate->writebyte ( '*' );
+                            insnTemplate << '*';
                         writeReg ( operand->reg );
                         /*
-                        insnTemplate->writestring("%");
-                        insnTemplate->writestring(regInfo[operand->reg].name);
+                        insnTemplate << "%";
+                        insnTemplate << regInfo[operand->reg].name;
                         */
                         break;
                     case Opr_Mem:
@@ -2061,8 +2052,7 @@
                         {
                             if ( operand->symbolDisplacement.dim )
                             {
-                                insnTemplate->printf ( "%d", operand->constDisplacement );
-                                insnTemplate->writebyte ( '+' );
+                                insnTemplate << operand->constDisplacement << '+';
                             }
                             //addOperand(fmt, Arg_Integer, newIntExp(operand->constDisplacement), asmcode);
                             if ( opInfo->operands[i] & Opr_Dest )
@@ -2072,7 +2062,7 @@
                         if ( operand->segmentPrefix != Reg_Invalid )
                         {
                             writeReg ( operand->segmentPrefix );
-                            insnTemplate->writebyte ( ':' );
+                            insnTemplate << ':';
                         }
                         if ( operand->symbolDisplacement.dim )
                         {
@@ -2163,15 +2153,15 @@
                                     // simply write out the mangle
                                     // on osx, prepend extra _
                                     if ( global.params.os == OSMacOSX )
-                                        insnTemplate->writestring ( "_" );
-                                    insnTemplate->writestring ( decl->mangle() );
+                                        insnTemplate << "_";
+                                    insnTemplate << decl->mangle();
 //              addOperand2("${", ":c}", Arg_Pointer, e, asmcode);
                                 }
                                 else
                                 {
                                     if ( use_star )
                                     {
-                                        insnTemplate->writebyte ( '*' );
+                                        insnTemplate << '*';
                                         use_star = false;
                                     }
 
@@ -2187,28 +2177,28 @@
                             }
                         }
                         if ( use_star )
-                            insnTemplate->writebyte ( '*' );
+                            insnTemplate << '*';
                         if ( operand->segmentPrefix != Reg_Invalid && !(operand->constDisplacement) )
                         {
-                            insnTemplate->printf ( "%d", operand->constDisplacement );
+                            insnTemplate << operand->constDisplacement;
                             if ( opInfo->operands[i] & Opr_Dest )
                                 asmcode->clobbersMemory = 1;
                         }
                         if ( operand->baseReg != Reg_Invalid || operand->indexReg != Reg_Invalid )
                         {
-                            insnTemplate->writebyte ( '(' );
+                            insnTemplate << '(';
                             if ( operand->baseReg != Reg_Invalid )
                                 writeReg ( operand->baseReg );
                             if ( operand->indexReg != Reg_Invalid )
                             {
-                                insnTemplate->writebyte ( ',' );
+                                insnTemplate << ',';
                                 writeReg ( operand->indexReg );
                                 if ( operand->scale )
                                 {
-                                    insnTemplate->printf ( ",%d", operand->scale );
+                                    insnTemplate << "," << operand->scale;
                                 }
                             }
-                            insnTemplate->writebyte ( ')' );
+                            insnTemplate << ')';
                             if ( opInfo->operands[i] & Opr_Dest )
                                 asmcode->clobbersMemory = 1;
                         }
@@ -2218,8 +2208,7 @@
                 }
             }
 
-            asmcode->insnTemplateLen = insnTemplate->offset;
-            asmcode->insnTemplate = ( char* ) insnTemplate->extractData();
+            asmcode->insnTemplate = insnTemplate.str();
             return true;
         }
 
@@ -2891,9 +2880,9 @@
                 //FIXME: This printf is not portable. The use of `align` varies from system to system;
                 // on i386 using a.out, .align `n` will align on a 2^`n` boundary instead of an `n` boundary
 #ifdef HAVE_GAS_BALIGN_AND_P2ALIGN
-                insnTemplate->printf ( ".balign\t%u", ( unsigned ) align );
+                insnTemplate << ".balign\t" << align;
 #else
-                insnTemplate->printf ( ".align\t%u", ( unsigned ) align );
+                insnTemplate << ".align\t" << align;
 #endif
             }
             else
@@ -2908,9 +2897,9 @@
         {
             // .align for GAS is in bits, others probably use bytes..
 #ifdef HAVE_GAS_BALIGN_AND_P2ALIGN
-            insnTemplate->writestring ( ( char * ) ".align\t2" );
+            insnTemplate << ".align\t2";
 #else
-            insnTemplate->writestring ( ( char * ) ".align\t2" );
+            insnTemplate << ".align\t2";
 #endif
             setAsmCode();
         }
--- a/gen/asm-x86-64.h	Thu Mar 12 14:08:57 2009 +0100
+++ b/gen/asm-x86-64.h	Thu Mar 12 14:08:57 2009 +0100
@@ -1328,7 +1328,7 @@
         Scope * sc;
 
         Token * token;
-        OutBuffer * insnTemplate;
+        std::ostringstream insnTemplate;
 
         AsmOp       op;
         AsmOpInfo * opInfo;
@@ -1341,7 +1341,6 @@
             this->sc = sc;
             this->stmt = stmt;
             token = stmt->tokens;
-            insnTemplate = new OutBuffer;
 
             opInfo = NULL;
 
@@ -1572,8 +1571,7 @@
         void setAsmCode()
         {
             AsmCode * asmcode = new AsmCode ( N_Regs );
-            asmcode->insnTemplateLen = insnTemplate->offset;
-            asmcode->insnTemplate = ( char* ) insnTemplate->extractData();
+            asmcode->insnTemplate = insnTemplate.str();
             stmt->asmcode = ( code* ) asmcode;
         }
 
@@ -1635,9 +1633,9 @@
                 {
                     case Arg_Integer:
                         if ( e->type->isunsigned() )
-                            insnTemplate->printf ( "$%llu", e->toUInteger() );
+                            insnTemplate << "$" << e->toUInteger();
                         else
-                            insnTemplate->printf ( "$%lld", e->toInteger() );
+                            insnTemplate << "$" << e->toInteger();
                         break;
 
                     case Arg_Pointer:
@@ -1658,10 +1656,10 @@
 
                                 // osx needs an extra underscore
                                 if ( global.params.os == OSMacOSX )
-                                    insnTemplate->writestring ( "_" );
+                                    insnTemplate << "_";
 
                                 // print out the mangle
-                                insnTemplate->writestring ( vd->mangle() );
+                                insnTemplate << vd->mangle();
                                 vd->nakedUse = true;
                                 break;
                             }
@@ -1676,25 +1674,23 @@
             }
             else
             {
-                insnTemplate->writestring ( ( char* ) fmt );
-                insnTemplate->printf ( "<<%s%d>>", ( mode==Mode_Input ) ?"in":"out", asmcode->args.size() );
+                insnTemplate << fmt
+                             << "<<" << (mode==Mode_Input ? "in" : "out") << asmcode->args.size() << ">>";
                 asmcode->args.push_back ( AsmArg ( type, e, mode ) );
             }
         }
         void addOperand2 ( const char * fmtpre, const char * fmtpost, AsmArgType type, Expression * e, AsmCode * asmcode, AsmArgMode mode = Mode_Input )
         {
             assert ( !sc->func->naked );
-            insnTemplate->writestring ( ( char* ) fmtpre );
-            insnTemplate->printf ( "<<%s%d>>", ( mode==Mode_Input ) ?"in":"out", asmcode->args.size() );
-            insnTemplate->writestring ( ( char* ) fmtpost );
+            insnTemplate << fmtpre
+                         << "<<" << (mode==Mode_Input ? "in" : "out") << ">>"
+                         << fmtpost;
             asmcode->args.push_back ( AsmArg ( type, e, mode ) );
         }
 
         void addLabel ( char* id )
         {
-            insnTemplate->writestring ( sc->func->mangle() );
-            insnTemplate->writestring ( "_" );
-            insnTemplate->writestring ( id );
+            insnTemplate << sc->func->mangle() <<  "_" << id;
         }
 
         /* Determines whether the operand is a register, memory reference
@@ -1778,8 +1774,7 @@
 
         void writeReg ( Reg reg )
         {
-            insnTemplate->writestring ( ( char* ) "%" );
-            insnTemplate->write ( regInfo[reg].gccName.c_str(), regInfo[reg].gccName.length() );
+            insnTemplate << "%" << regInfo[reg].gccName;
         }
 
         bool opTakesLabel()
@@ -1852,7 +1847,7 @@
             bool use_star;
             AsmArgMode mode;
 
-            insnTemplate = new OutBuffer;
+            insnTemplate.str("");
             // %% todo: special case for something..
             if ( opInfo->linkType == Out_Mnemonic )
                 mnemonic = alternateMnemonics[opInfo->link];
@@ -1921,7 +1916,7 @@
             else if ( op == Op_Branch )
             {
                 if ( operands[0].dataSize == Far_Ptr ) // %% type=Far_Ptr not set by Seg:Ofss OTOH, we don't support that..
-                    insnTemplate->writebyte ( 'l' );
+                    insnTemplate << 'l';
             }
             else if ( op == Op_fxch || op == Op_FfdRR_P || op == Op_FidR_P )
             {
@@ -1959,11 +1954,10 @@
                 {
                     int mlen = strlen ( mnemonic );
                     if ( mnemonic[mlen-1] == 'd' )
-                        insnTemplate->write ( mnemonic, mlen-1 );
+                        insnTemplate.write(mnemonic, mlen-1);
                     else
                     {
-                        insnTemplate->writestring ( ( char* ) mnemonic );
-                        insnTemplate->writebyte ( 'w' );
+                        insnTemplate << mnemonic << 'w';
                     }
                 }
                 break;
@@ -1978,12 +1972,11 @@
                     int mlen = strlen ( mnemonic );
                     if ( mnemonic[mlen-1] == 'd' )
                     {
-                        insnTemplate->write ( mnemonic, mlen-1 );
-                        insnTemplate->writebyte ( 'l' );
+                        insnTemplate.write(mnemonic, mlen-1) << 'l';
                     }
                     else
                     {
-                        insnTemplate->writestring ( ( char* ) mnemonic );
+                        insnTemplate << mnemonic;
                     }
                 }
                 break;
@@ -2010,15 +2003,13 @@
                             return false;
                     }
                     assert ( type_char != 0 );
-                    insnTemplate->write ( mnemonic, mlen-1 );
-                    insnTemplate->writebyte ( tc_1 );
-                    insnTemplate->writebyte ( type_char );
+                    insnTemplate.write(mnemonic, mlen-1) << tc_1 << type_char;
                 }
                 break;
                 default:
-                    insnTemplate->writestring ( ( char* ) mnemonic );
+                    insnTemplate << mnemonic;
                     if ( type_char )
-                        insnTemplate->writebyte ( type_char );
+                        insnTemplate << type_char;
                     break;
             }
 
@@ -2072,12 +2063,12 @@
                 asmcode->regs[Reg_EDX] = true;
             }
 
-            insnTemplate->writebyte ( ' ' );
+            insnTemplate << ' ';
             for ( int i__ = 0; i__ < nOperands; i__++ )
             {
                 int i;
                 if ( i__ != 0 )
-                    insnTemplate->writestring ( ( char* ) ", " );
+                    insnTemplate << ", ";
 
                 fmt = "$";
 
@@ -2125,7 +2116,7 @@
                             addOperand ( "$", Arg_LocalSize,
                                          ( Expression * ) operand->symbolDisplacement.data[0], asmcode );
                             if ( operand->constDisplacement )
-                                insnTemplate->writebyte ( '+' );
+                                insnTemplate << '+';
                             else
                                 break;
                         }
@@ -2138,7 +2129,7 @@
                                          asmcode );
 
                             if ( operand->constDisplacement )
-                                insnTemplate->writebyte ( '+' );
+                                insnTemplate << '+';
                             else
                                 // skip the addOperand(fmt, Arg_Integer...) below
                                 break;
@@ -2155,11 +2146,11 @@
                             }
                         }
                         if ( opTakesLabel() /*opInfo->takesLabel()*/ )
-                            insnTemplate->writebyte ( '*' );
+                            insnTemplate << '*';
                         writeReg ( operand->reg );
                         /*
-                        insnTemplate->writestring("%");
-                        insnTemplate->writestring(regInfo[operand->reg].name);
+                        insnTemplate << "%";
+                        insnTemplate << regInfo[operand->reg].name;
                         */
                         break;
                     case Opr_Mem:
@@ -2183,8 +2174,7 @@
                         {
                             if ( operand->symbolDisplacement.dim )
                             {
-                                insnTemplate->printf ( "%d", operand->constDisplacement );
-                                insnTemplate->writebyte ( '+' );
+                                insnTemplate << operand->constDisplacement << '+';
                             }
                             //addOperand(fmt, Arg_Integer, newIntExp(operand->constDisplacement), asmcode);
                             if ( opInfo->operands[i] & Opr_Dest )
@@ -2194,7 +2184,7 @@
                         if ( operand->segmentPrefix != Reg_Invalid )
                         {
                             writeReg ( operand->segmentPrefix );
-                            insnTemplate->writebyte ( ':' );
+                            insnTemplate << ':';
                         }
                         if ( operand->symbolDisplacement.dim )
                         {
@@ -2285,15 +2275,15 @@
                                     // simply write out the mangle
                                     // on osx, prepend extra _
                                     if ( global.params.os == OSMacOSX )
-                                        insnTemplate->writestring ( "_" );
-                                    insnTemplate->writestring ( decl->mangle() );
+                                        insnTemplate << "_";
+                                    insnTemplate << decl->mangle();
 //              addOperand2("${", ":c}", Arg_Pointer, e, asmcode);
                                 }
                                 else
                                 {
                                     if ( use_star )
                                     {
-                                        insnTemplate->writebyte ( '*' );
+                                        insnTemplate << '*';
                                         use_star = false;
                                     }
 
@@ -2309,28 +2299,28 @@
                             }
                         }
                         if ( use_star )
-                            insnTemplate->writebyte ( '*' );
+                            insnTemplate << '*';
                         if ( operand->segmentPrefix != Reg_Invalid && !(operand->constDisplacement))
                         {
-                            insnTemplate->printf ( "%d", operand->constDisplacement );
+                            insnTemplate << operand->constDisplacement;
                             if ( opInfo->operands[i] & Opr_Dest )
                                 asmcode->clobbersMemory = 1;
                         }
                         if ( operand->baseReg != Reg_Invalid || operand->indexReg != Reg_Invalid )
                         {
-                            insnTemplate->writebyte ( '(' );
+                            insnTemplate << '(';
                             if ( operand->baseReg != Reg_Invalid )
                                 writeReg ( operand->baseReg );
                             if ( operand->indexReg != Reg_Invalid )
                             {
-                                insnTemplate->writebyte ( ',' );
+                                insnTemplate << ',';
                                 writeReg ( operand->indexReg );
                                 if ( operand->scale )
                                 {
-                                    insnTemplate->printf ( ",%d", operand->scale );
+                                    insnTemplate << "," << operand->scale;
                                 }
                             }
-                            insnTemplate->writebyte ( ')' );
+                            insnTemplate << ')';
                             if ( opInfo->operands[i] & Opr_Dest )
                                 asmcode->clobbersMemory = 1;
                         }
@@ -2340,8 +2330,7 @@
                 }
             }
 
-            asmcode->insnTemplateLen = insnTemplate->offset;
-            asmcode->insnTemplate = ( char* ) insnTemplate->extractData();
+            asmcode->insnTemplate = insnTemplate.str();
             return true;
         }
 
@@ -3016,9 +3005,9 @@
                 //FIXME: This printf is not portable. The use of `align` varies from system to system;
                 // on i386 using a.out, .align `n` will align on a 2^`n` boundary instead of an `n` boundary
 #ifdef HAVE_GAS_BALIGN_AND_P2ALIGN
-                insnTemplate->printf ( ".balign\t%u", ( unsigned ) align );
+                insnTemplate << ".balign\t" << align;
 #else
-                insnTemplate->printf ( ".align\t%u", ( unsigned ) align );
+                insnTemplate << ".align\t" << align;
 #endif
             }
             else
@@ -3033,9 +3022,9 @@
         {
             // .align for GAS is in bits, others probably use bytes..
 #ifdef HAVE_GAS_BALIGN_AND_P2ALIGN
-            insnTemplate->writestring ( ( char * ) ".align\t2" );
+            insnTemplate << ".align\t2";
 #else
-            insnTemplate->writestring ( ( char * ) ".align\t2" );
+            insnTemplate << ".align\t2";
 #endif
             setAsmCode();
         }
--- a/gen/asmstmt.cpp	Thu Mar 12 14:08:57 2009 +0100
+++ b/gen/asmstmt.cpp	Thu Mar 12 14:08:57 2009 +0100
@@ -15,6 +15,8 @@
 #include <cassert>
 #include <deque>
 #include <cstring>
+#include <string>
+#include <sstream>
 
 //#include "d-lang.h"
 //#include "d-codegen.h"
@@ -54,15 +56,12 @@
 };
 
 struct AsmCode {
-    char *   insnTemplate;
-    unsigned insnTemplateLen;
+    std::string insnTemplate;
     std::vector<AsmArg> args;
     std::vector<bool> regs;
     unsigned dollarLabel;
     int      clobbersMemory;
     AsmCode(int n_regs) {
-	insnTemplate = NULL;
-	insnTemplateLen = 0;
 	regs.resize(n_regs, false);
 	dollarLabel = 0;
 	clobbersMemory = 0;
@@ -314,7 +313,6 @@
 	    clobbers.push_back(memory_name);
 //    }
 
-
     // Remap argument numbers
     for (unsigned i = 0; i < code->args.size(); i++) {
 	if (arg_map[i] < 0)
@@ -322,8 +320,9 @@
     }
     
     bool pct = false;
-    char * p = code->insnTemplate;
-    char * q = p + code->insnTemplateLen;
+    std::string::iterator
+        p = code->insnTemplate.begin(),
+        q = code->insnTemplate.end();
     //printf("start: %.*s\n", code->insnTemplateLen, code->insnTemplate);
     while (p < q) {
 	if (pct) {
@@ -342,7 +341,7 @@
 
     typedef std::vector<std::string>::iterator It;
     if (Logger::enabled()) {
-        Logger::println("final asm: %.*s", code->insnTemplateLen, code->insnTemplate);
+        Logger::cout() << "final asm: " << code->insnTemplate << '\n';
         std::ostringstream ss;
         
         ss << "GCC-style output constraints: {";
@@ -369,8 +368,6 @@
         Logger::println("%s", ss.str().c_str());
     }
 
-    std::string insnt(code->insnTemplate, code->insnTemplateLen);
-
     // rewrite GCC-style constraints to LLVM-style constraints
     std::string llvmOutConstraints;
     std::string llvmInConstraints;
@@ -433,7 +430,7 @@
 
     // push asm statement
     IRAsmStmt* asmStmt = new IRAsmStmt;
-    asmStmt->code = insnt;
+    asmStmt->code = code->insnTemplate;
     asmStmt->out_c = llvmOutConstraints;
     asmStmt->in_c = llvmInConstraints;
     asmStmt->out.insert(asmStmt->out.begin(), output_values.begin(), output_values.end());
@@ -825,10 +822,7 @@
     AsmCode * code = (AsmCode *) asmcode;
 
     // build asm stmt
-    std::ostringstream& asmstr = p->nakedAsm;
-    asmstr << "\t";
-    asmstr.write(code->insnTemplate, code->insnTemplateLen);
-    asmstr << std::endl;
+    p->nakedAsm << "\t" << code->insnTemplate << std::endl;
 }
 
 void AsmBlockStatement::toNakedIR(IRState *p)