# HG changeset patch # User Frits van Bommel # Date 1236863337 -3600 # Node ID ae950bd712d35f0fced99fcf06671877c1e96a34 # Parent 8bf8b058944a05a7354b3a69af49b4401e31b108 Use stringstream in asm generation instead of OutBuffer. Besides looking better, this should reduce allocations and copying. diff -r 8bf8b058944a -r ae950bd712d3 gen/asm-x86-32.h --- 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(); } diff -r 8bf8b058944a -r ae950bd712d3 gen/asm-x86-64.h --- 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(); } diff -r 8bf8b058944a -r ae950bd712d3 gen/asmstmt.cpp --- 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 #include #include +#include +#include //#include "d-lang.h" //#include "d-codegen.h" @@ -54,15 +56,12 @@ }; struct AsmCode { - char * insnTemplate; - unsigned insnTemplateLen; + std::string insnTemplate; std::vector args; std::vector 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::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)