Mercurial > projects > ldc
comparison gen/asm-x86-64.h @ 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 | d03814546977 |
comparison
equal
deleted
inserted
replaced
1101:8bf8b058944a | 1102:ae950bd712d3 |
---|---|
1326 | 1326 |
1327 AsmStatement * stmt; | 1327 AsmStatement * stmt; |
1328 Scope * sc; | 1328 Scope * sc; |
1329 | 1329 |
1330 Token * token; | 1330 Token * token; |
1331 OutBuffer * insnTemplate; | 1331 std::ostringstream insnTemplate; |
1332 | 1332 |
1333 AsmOp op; | 1333 AsmOp op; |
1334 AsmOpInfo * opInfo; | 1334 AsmOpInfo * opInfo; |
1335 Operand operands[Max_Operands]; | 1335 Operand operands[Max_Operands]; |
1336 Identifier * opIdent; | 1336 Identifier * opIdent; |
1339 AsmProcessor ( Scope * sc, AsmStatement * stmt ) | 1339 AsmProcessor ( Scope * sc, AsmStatement * stmt ) |
1340 { | 1340 { |
1341 this->sc = sc; | 1341 this->sc = sc; |
1342 this->stmt = stmt; | 1342 this->stmt = stmt; |
1343 token = stmt->tokens; | 1343 token = stmt->tokens; |
1344 insnTemplate = new OutBuffer; | |
1345 | 1344 |
1346 opInfo = NULL; | 1345 opInfo = NULL; |
1347 | 1346 |
1348 if ( ! regInfo[0].ident ) | 1347 if ( ! regInfo[0].ident ) |
1349 { | 1348 { |
1570 } | 1569 } |
1571 | 1570 |
1572 void setAsmCode() | 1571 void setAsmCode() |
1573 { | 1572 { |
1574 AsmCode * asmcode = new AsmCode ( N_Regs ); | 1573 AsmCode * asmcode = new AsmCode ( N_Regs ); |
1575 asmcode->insnTemplateLen = insnTemplate->offset; | 1574 asmcode->insnTemplate = insnTemplate.str(); |
1576 asmcode->insnTemplate = ( char* ) insnTemplate->extractData(); | |
1577 stmt->asmcode = ( code* ) asmcode; | 1575 stmt->asmcode = ( code* ) asmcode; |
1578 } | 1576 } |
1579 | 1577 |
1580 // note: doesn't update AsmOp op | 1578 // note: doesn't update AsmOp op |
1581 bool matchOperands ( unsigned nOperands ) | 1579 bool matchOperands ( unsigned nOperands ) |
1633 { | 1631 { |
1634 switch ( type ) | 1632 switch ( type ) |
1635 { | 1633 { |
1636 case Arg_Integer: | 1634 case Arg_Integer: |
1637 if ( e->type->isunsigned() ) | 1635 if ( e->type->isunsigned() ) |
1638 insnTemplate->printf ( "$%llu", e->toUInteger() ); | 1636 insnTemplate << "$" << e->toUInteger(); |
1639 else | 1637 else |
1640 insnTemplate->printf ( "$%lld", e->toInteger() ); | 1638 insnTemplate << "$" << e->toInteger(); |
1641 break; | 1639 break; |
1642 | 1640 |
1643 case Arg_Pointer: | 1641 case Arg_Pointer: |
1644 stmt->error ( "unsupported pointer reference to '%s' in naked asm", e->toChars() ); | 1642 stmt->error ( "unsupported pointer reference to '%s' in naked asm", e->toChars() ); |
1645 break; | 1643 break; |
1656 break; | 1654 break; |
1657 } | 1655 } |
1658 | 1656 |
1659 // osx needs an extra underscore | 1657 // osx needs an extra underscore |
1660 if ( global.params.os == OSMacOSX ) | 1658 if ( global.params.os == OSMacOSX ) |
1661 insnTemplate->writestring ( "_" ); | 1659 insnTemplate << "_"; |
1662 | 1660 |
1663 // print out the mangle | 1661 // print out the mangle |
1664 insnTemplate->writestring ( vd->mangle() ); | 1662 insnTemplate << vd->mangle(); |
1665 vd->nakedUse = true; | 1663 vd->nakedUse = true; |
1666 break; | 1664 break; |
1667 } | 1665 } |
1668 } | 1666 } |
1669 stmt->error ( "unsupported memory reference to '%s' in naked asm", e->toChars() ); | 1667 stmt->error ( "unsupported memory reference to '%s' in naked asm", e->toChars() ); |
1674 break; | 1672 break; |
1675 } | 1673 } |
1676 } | 1674 } |
1677 else | 1675 else |
1678 { | 1676 { |
1679 insnTemplate->writestring ( ( char* ) fmt ); | 1677 insnTemplate << fmt |
1680 insnTemplate->printf ( "<<%s%d>>", ( mode==Mode_Input ) ?"in":"out", asmcode->args.size() ); | 1678 << "<<" << (mode==Mode_Input ? "in" : "out") << asmcode->args.size() << ">>"; |
1681 asmcode->args.push_back ( AsmArg ( type, e, mode ) ); | 1679 asmcode->args.push_back ( AsmArg ( type, e, mode ) ); |
1682 } | 1680 } |
1683 } | 1681 } |
1684 void addOperand2 ( const char * fmtpre, const char * fmtpost, AsmArgType type, Expression * e, AsmCode * asmcode, AsmArgMode mode = Mode_Input ) | 1682 void addOperand2 ( const char * fmtpre, const char * fmtpost, AsmArgType type, Expression * e, AsmCode * asmcode, AsmArgMode mode = Mode_Input ) |
1685 { | 1683 { |
1686 assert ( !sc->func->naked ); | 1684 assert ( !sc->func->naked ); |
1687 insnTemplate->writestring ( ( char* ) fmtpre ); | 1685 insnTemplate << fmtpre |
1688 insnTemplate->printf ( "<<%s%d>>", ( mode==Mode_Input ) ?"in":"out", asmcode->args.size() ); | 1686 << "<<" << (mode==Mode_Input ? "in" : "out") << ">>" |
1689 insnTemplate->writestring ( ( char* ) fmtpost ); | 1687 << fmtpost; |
1690 asmcode->args.push_back ( AsmArg ( type, e, mode ) ); | 1688 asmcode->args.push_back ( AsmArg ( type, e, mode ) ); |
1691 } | 1689 } |
1692 | 1690 |
1693 void addLabel ( char* id ) | 1691 void addLabel ( char* id ) |
1694 { | 1692 { |
1695 insnTemplate->writestring ( sc->func->mangle() ); | 1693 insnTemplate << sc->func->mangle() << "_" << id; |
1696 insnTemplate->writestring ( "_" ); | |
1697 insnTemplate->writestring ( id ); | |
1698 } | 1694 } |
1699 | 1695 |
1700 /* Determines whether the operand is a register, memory reference | 1696 /* Determines whether the operand is a register, memory reference |
1701 or immediate. Immediate addresses are currently classified as | 1697 or immediate. Immediate addresses are currently classified as |
1702 memory. This function is called before the exact instructions | 1698 memory. This function is called before the exact instructions |
1776 return Opr_Invalid; | 1772 return Opr_Invalid; |
1777 } | 1773 } |
1778 | 1774 |
1779 void writeReg ( Reg reg ) | 1775 void writeReg ( Reg reg ) |
1780 { | 1776 { |
1781 insnTemplate->writestring ( ( char* ) "%" ); | 1777 insnTemplate << "%" << regInfo[reg].gccName; |
1782 insnTemplate->write ( regInfo[reg].gccName.c_str(), regInfo[reg].gccName.length() ); | |
1783 } | 1778 } |
1784 | 1779 |
1785 bool opTakesLabel() | 1780 bool opTakesLabel() |
1786 { | 1781 { |
1787 switch ( op ) | 1782 switch ( op ) |
1850 const char *mnemonic; | 1845 const char *mnemonic; |
1851 char type_char = 0; | 1846 char type_char = 0; |
1852 bool use_star; | 1847 bool use_star; |
1853 AsmArgMode mode; | 1848 AsmArgMode mode; |
1854 | 1849 |
1855 insnTemplate = new OutBuffer; | 1850 insnTemplate.str(""); |
1856 // %% todo: special case for something.. | 1851 // %% todo: special case for something.. |
1857 if ( opInfo->linkType == Out_Mnemonic ) | 1852 if ( opInfo->linkType == Out_Mnemonic ) |
1858 mnemonic = alternateMnemonics[opInfo->link]; | 1853 mnemonic = alternateMnemonics[opInfo->link]; |
1859 else | 1854 else |
1860 mnemonic = opIdent->string; | 1855 mnemonic = opIdent->string; |
1919 } | 1914 } |
1920 } | 1915 } |
1921 else if ( op == Op_Branch ) | 1916 else if ( op == Op_Branch ) |
1922 { | 1917 { |
1923 if ( operands[0].dataSize == Far_Ptr ) // %% type=Far_Ptr not set by Seg:Ofss OTOH, we don't support that.. | 1918 if ( operands[0].dataSize == Far_Ptr ) // %% type=Far_Ptr not set by Seg:Ofss OTOH, we don't support that.. |
1924 insnTemplate->writebyte ( 'l' ); | 1919 insnTemplate << 'l'; |
1925 } | 1920 } |
1926 else if ( op == Op_fxch || op == Op_FfdRR_P || op == Op_FidR_P ) | 1921 else if ( op == Op_fxch || op == Op_FfdRR_P || op == Op_FidR_P ) |
1927 { | 1922 { |
1928 if ( operands[0].cls == Opr_Mem && op == Op_FidR_P ) | 1923 if ( operands[0].cls == Opr_Mem && op == Op_FidR_P ) |
1929 { | 1924 { |
1957 { | 1952 { |
1958 case Op_SizedStack: | 1953 case Op_SizedStack: |
1959 { | 1954 { |
1960 int mlen = strlen ( mnemonic ); | 1955 int mlen = strlen ( mnemonic ); |
1961 if ( mnemonic[mlen-1] == 'd' ) | 1956 if ( mnemonic[mlen-1] == 'd' ) |
1962 insnTemplate->write ( mnemonic, mlen-1 ); | 1957 insnTemplate.write(mnemonic, mlen-1); |
1963 else | 1958 else |
1964 { | 1959 { |
1965 insnTemplate->writestring ( ( char* ) mnemonic ); | 1960 insnTemplate << mnemonic << 'w'; |
1966 insnTemplate->writebyte ( 'w' ); | |
1967 } | 1961 } |
1968 } | 1962 } |
1969 break; | 1963 break; |
1970 case Op_cmpsd: | 1964 case Op_cmpsd: |
1971 case Op_insX: | 1965 case Op_insX: |
1976 case Op_stosX: | 1970 case Op_stosX: |
1977 { | 1971 { |
1978 int mlen = strlen ( mnemonic ); | 1972 int mlen = strlen ( mnemonic ); |
1979 if ( mnemonic[mlen-1] == 'd' ) | 1973 if ( mnemonic[mlen-1] == 'd' ) |
1980 { | 1974 { |
1981 insnTemplate->write ( mnemonic, mlen-1 ); | 1975 insnTemplate.write(mnemonic, mlen-1) << 'l'; |
1982 insnTemplate->writebyte ( 'l' ); | |
1983 } | 1976 } |
1984 else | 1977 else |
1985 { | 1978 { |
1986 insnTemplate->writestring ( ( char* ) mnemonic ); | 1979 insnTemplate << mnemonic; |
1987 } | 1980 } |
1988 } | 1981 } |
1989 break; | 1982 break; |
1990 case Op_movsx: | 1983 case Op_movsx: |
1991 case Op_movzx: | 1984 case Op_movzx: |
2008 default: | 2001 default: |
2009 stmt->error ( "invalid operand size/type" ); | 2002 stmt->error ( "invalid operand size/type" ); |
2010 return false; | 2003 return false; |
2011 } | 2004 } |
2012 assert ( type_char != 0 ); | 2005 assert ( type_char != 0 ); |
2013 insnTemplate->write ( mnemonic, mlen-1 ); | 2006 insnTemplate.write(mnemonic, mlen-1) << tc_1 << type_char; |
2014 insnTemplate->writebyte ( tc_1 ); | |
2015 insnTemplate->writebyte ( type_char ); | |
2016 } | 2007 } |
2017 break; | 2008 break; |
2018 default: | 2009 default: |
2019 insnTemplate->writestring ( ( char* ) mnemonic ); | 2010 insnTemplate << mnemonic; |
2020 if ( type_char ) | 2011 if ( type_char ) |
2021 insnTemplate->writebyte ( type_char ); | 2012 insnTemplate << type_char; |
2022 break; | 2013 break; |
2023 } | 2014 } |
2024 | 2015 |
2025 switch ( opInfo->implicitClobbers & Clb_DXAX_Mask ) | 2016 switch ( opInfo->implicitClobbers & Clb_DXAX_Mask ) |
2026 { | 2017 { |
2070 asmcode->regs[Reg_EBX] = true; | 2061 asmcode->regs[Reg_EBX] = true; |
2071 asmcode->regs[Reg_ECX] = true; | 2062 asmcode->regs[Reg_ECX] = true; |
2072 asmcode->regs[Reg_EDX] = true; | 2063 asmcode->regs[Reg_EDX] = true; |
2073 } | 2064 } |
2074 | 2065 |
2075 insnTemplate->writebyte ( ' ' ); | 2066 insnTemplate << ' '; |
2076 for ( int i__ = 0; i__ < nOperands; i__++ ) | 2067 for ( int i__ = 0; i__ < nOperands; i__++ ) |
2077 { | 2068 { |
2078 int i; | 2069 int i; |
2079 if ( i__ != 0 ) | 2070 if ( i__ != 0 ) |
2080 insnTemplate->writestring ( ( char* ) ", " ); | 2071 insnTemplate << ", "; |
2081 | 2072 |
2082 fmt = "$"; | 2073 fmt = "$"; |
2083 | 2074 |
2084 switch ( op ) | 2075 switch ( op ) |
2085 { | 2076 { |
2123 // handle __LOCAL_SIZE, which in this constant, is an immediate | 2114 // handle __LOCAL_SIZE, which in this constant, is an immediate |
2124 // should do this in slotexp.. | 2115 // should do this in slotexp.. |
2125 addOperand ( "$", Arg_LocalSize, | 2116 addOperand ( "$", Arg_LocalSize, |
2126 ( Expression * ) operand->symbolDisplacement.data[0], asmcode ); | 2117 ( Expression * ) operand->symbolDisplacement.data[0], asmcode ); |
2127 if ( operand->constDisplacement ) | 2118 if ( operand->constDisplacement ) |
2128 insnTemplate->writebyte ( '+' ); | 2119 insnTemplate << '+'; |
2129 else | 2120 else |
2130 break; | 2121 break; |
2131 } | 2122 } |
2132 | 2123 |
2133 if ( operand->symbolDisplacement.dim ) | 2124 if ( operand->symbolDisplacement.dim ) |
2136 addOperand ( "$", Arg_Pointer, | 2127 addOperand ( "$", Arg_Pointer, |
2137 ( Expression * ) operand->symbolDisplacement.data[0], | 2128 ( Expression * ) operand->symbolDisplacement.data[0], |
2138 asmcode ); | 2129 asmcode ); |
2139 | 2130 |
2140 if ( operand->constDisplacement ) | 2131 if ( operand->constDisplacement ) |
2141 insnTemplate->writebyte ( '+' ); | 2132 insnTemplate << '+'; |
2142 else | 2133 else |
2143 // skip the addOperand(fmt, Arg_Integer...) below | 2134 // skip the addOperand(fmt, Arg_Integer...) below |
2144 break; | 2135 break; |
2145 } | 2136 } |
2146 addOperand ( fmt, Arg_Integer, newIntExp ( operand->constDisplacement ), asmcode ); | 2137 addOperand ( fmt, Arg_Integer, newIntExp ( operand->constDisplacement ), asmcode ); |
2153 { | 2144 { |
2154 asmcode->regs[clbr_reg] = true; | 2145 asmcode->regs[clbr_reg] = true; |
2155 } | 2146 } |
2156 } | 2147 } |
2157 if ( opTakesLabel() /*opInfo->takesLabel()*/ ) | 2148 if ( opTakesLabel() /*opInfo->takesLabel()*/ ) |
2158 insnTemplate->writebyte ( '*' ); | 2149 insnTemplate << '*'; |
2159 writeReg ( operand->reg ); | 2150 writeReg ( operand->reg ); |
2160 /* | 2151 /* |
2161 insnTemplate->writestring("%"); | 2152 insnTemplate << "%"; |
2162 insnTemplate->writestring(regInfo[operand->reg].name); | 2153 insnTemplate << regInfo[operand->reg].name; |
2163 */ | 2154 */ |
2164 break; | 2155 break; |
2165 case Opr_Mem: | 2156 case Opr_Mem: |
2166 // better: use output operands for simple variable references | 2157 // better: use output operands for simple variable references |
2167 if ( ( opInfo->operands[i] & Opr_Update ) == Opr_Update ) | 2158 if ( ( opInfo->operands[i] & Opr_Update ) == Opr_Update ) |
2181 | 2172 |
2182 if ( operand->segmentPrefix != Reg_Invalid || operand->constDisplacement ) | 2173 if ( operand->segmentPrefix != Reg_Invalid || operand->constDisplacement ) |
2183 { | 2174 { |
2184 if ( operand->symbolDisplacement.dim ) | 2175 if ( operand->symbolDisplacement.dim ) |
2185 { | 2176 { |
2186 insnTemplate->printf ( "%d", operand->constDisplacement ); | 2177 insnTemplate << operand->constDisplacement << '+'; |
2187 insnTemplate->writebyte ( '+' ); | |
2188 } | 2178 } |
2189 //addOperand(fmt, Arg_Integer, newIntExp(operand->constDisplacement), asmcode); | 2179 //addOperand(fmt, Arg_Integer, newIntExp(operand->constDisplacement), asmcode); |
2190 if ( opInfo->operands[i] & Opr_Dest ) | 2180 if ( opInfo->operands[i] & Opr_Dest ) |
2191 asmcode->clobbersMemory = 1; | 2181 asmcode->clobbersMemory = 1; |
2192 } | 2182 } |
2193 | 2183 |
2194 if ( operand->segmentPrefix != Reg_Invalid ) | 2184 if ( operand->segmentPrefix != Reg_Invalid ) |
2195 { | 2185 { |
2196 writeReg ( operand->segmentPrefix ); | 2186 writeReg ( operand->segmentPrefix ); |
2197 insnTemplate->writebyte ( ':' ); | 2187 insnTemplate << ':'; |
2198 } | 2188 } |
2199 if ( operand->symbolDisplacement.dim ) | 2189 if ( operand->symbolDisplacement.dim ) |
2200 { | 2190 { |
2201 Expression * e = ( Expression * ) operand->symbolDisplacement.data[0]; | 2191 Expression * e = ( Expression * ) operand->symbolDisplacement.data[0]; |
2202 Declaration * decl = 0; | 2192 Declaration * decl = 0; |
2283 { | 2273 { |
2284 use_star = false; | 2274 use_star = false; |
2285 // simply write out the mangle | 2275 // simply write out the mangle |
2286 // on osx, prepend extra _ | 2276 // on osx, prepend extra _ |
2287 if ( global.params.os == OSMacOSX ) | 2277 if ( global.params.os == OSMacOSX ) |
2288 insnTemplate->writestring ( "_" ); | 2278 insnTemplate << "_"; |
2289 insnTemplate->writestring ( decl->mangle() ); | 2279 insnTemplate << decl->mangle(); |
2290 // addOperand2("${", ":c}", Arg_Pointer, e, asmcode); | 2280 // addOperand2("${", ":c}", Arg_Pointer, e, asmcode); |
2291 } | 2281 } |
2292 else | 2282 else |
2293 { | 2283 { |
2294 if ( use_star ) | 2284 if ( use_star ) |
2295 { | 2285 { |
2296 insnTemplate->writebyte ( '*' ); | 2286 insnTemplate << '*'; |
2297 use_star = false; | 2287 use_star = false; |
2298 } | 2288 } |
2299 | 2289 |
2300 if ( !sc->func->naked ) // no addrexp in naked asm please :) | 2290 if ( !sc->func->naked ) // no addrexp in naked asm please :) |
2301 { | 2291 { |
2307 addOperand ( fmt, Arg_Memory, e, asmcode, mode ); | 2297 addOperand ( fmt, Arg_Memory, e, asmcode, mode ); |
2308 } | 2298 } |
2309 } | 2299 } |
2310 } | 2300 } |
2311 if ( use_star ) | 2301 if ( use_star ) |
2312 insnTemplate->writebyte ( '*' ); | 2302 insnTemplate << '*'; |
2313 if ( operand->segmentPrefix != Reg_Invalid && !(operand->constDisplacement)) | 2303 if ( operand->segmentPrefix != Reg_Invalid && !(operand->constDisplacement)) |
2314 { | 2304 { |
2315 insnTemplate->printf ( "%d", operand->constDisplacement ); | 2305 insnTemplate << operand->constDisplacement; |
2316 if ( opInfo->operands[i] & Opr_Dest ) | 2306 if ( opInfo->operands[i] & Opr_Dest ) |
2317 asmcode->clobbersMemory = 1; | 2307 asmcode->clobbersMemory = 1; |
2318 } | 2308 } |
2319 if ( operand->baseReg != Reg_Invalid || operand->indexReg != Reg_Invalid ) | 2309 if ( operand->baseReg != Reg_Invalid || operand->indexReg != Reg_Invalid ) |
2320 { | 2310 { |
2321 insnTemplate->writebyte ( '(' ); | 2311 insnTemplate << '('; |
2322 if ( operand->baseReg != Reg_Invalid ) | 2312 if ( operand->baseReg != Reg_Invalid ) |
2323 writeReg ( operand->baseReg ); | 2313 writeReg ( operand->baseReg ); |
2324 if ( operand->indexReg != Reg_Invalid ) | 2314 if ( operand->indexReg != Reg_Invalid ) |
2325 { | 2315 { |
2326 insnTemplate->writebyte ( ',' ); | 2316 insnTemplate << ','; |
2327 writeReg ( operand->indexReg ); | 2317 writeReg ( operand->indexReg ); |
2328 if ( operand->scale ) | 2318 if ( operand->scale ) |
2329 { | 2319 { |
2330 insnTemplate->printf ( ",%d", operand->scale ); | 2320 insnTemplate << "," << operand->scale; |
2331 } | 2321 } |
2332 } | 2322 } |
2333 insnTemplate->writebyte ( ')' ); | 2323 insnTemplate << ')'; |
2334 if ( opInfo->operands[i] & Opr_Dest ) | 2324 if ( opInfo->operands[i] & Opr_Dest ) |
2335 asmcode->clobbersMemory = 1; | 2325 asmcode->clobbersMemory = 1; |
2336 } | 2326 } |
2337 break; | 2327 break; |
2338 case Opr_Invalid: | 2328 case Opr_Invalid: |
2339 return false; | 2329 return false; |
2340 } | 2330 } |
2341 } | 2331 } |
2342 | 2332 |
2343 asmcode->insnTemplateLen = insnTemplate->offset; | 2333 asmcode->insnTemplate = insnTemplate.str(); |
2344 asmcode->insnTemplate = ( char* ) insnTemplate->extractData(); | |
2345 return true; | 2334 return true; |
2346 } | 2335 } |
2347 | 2336 |
2348 bool isIntExp ( Expression * exp ) | 2337 bool isIntExp ( Expression * exp ) |
2349 { | 2338 { |
3014 if ( ( align & ( align - 1 ) ) == 0 ) | 3003 if ( ( align & ( align - 1 ) ) == 0 ) |
3015 { | 3004 { |
3016 //FIXME: This printf is not portable. The use of `align` varies from system to system; | 3005 //FIXME: This printf is not portable. The use of `align` varies from system to system; |
3017 // on i386 using a.out, .align `n` will align on a 2^`n` boundary instead of an `n` boundary | 3006 // on i386 using a.out, .align `n` will align on a 2^`n` boundary instead of an `n` boundary |
3018 #ifdef HAVE_GAS_BALIGN_AND_P2ALIGN | 3007 #ifdef HAVE_GAS_BALIGN_AND_P2ALIGN |
3019 insnTemplate->printf ( ".balign\t%u", ( unsigned ) align ); | 3008 insnTemplate << ".balign\t" << align; |
3020 #else | 3009 #else |
3021 insnTemplate->printf ( ".align\t%u", ( unsigned ) align ); | 3010 insnTemplate << ".align\t" << align; |
3022 #endif | 3011 #endif |
3023 } | 3012 } |
3024 else | 3013 else |
3025 { | 3014 { |
3026 stmt->error ( "alignment must be a power of 2, not %u", ( unsigned ) align ); | 3015 stmt->error ( "alignment must be a power of 2, not %u", ( unsigned ) align ); |
3031 | 3020 |
3032 void doEven() | 3021 void doEven() |
3033 { | 3022 { |
3034 // .align for GAS is in bits, others probably use bytes.. | 3023 // .align for GAS is in bits, others probably use bytes.. |
3035 #ifdef HAVE_GAS_BALIGN_AND_P2ALIGN | 3024 #ifdef HAVE_GAS_BALIGN_AND_P2ALIGN |
3036 insnTemplate->writestring ( ( char * ) ".align\t2" ); | 3025 insnTemplate << ".align\t2"; |
3037 #else | 3026 #else |
3038 insnTemplate->writestring ( ( char * ) ".align\t2" ); | 3027 insnTemplate << ".align\t2"; |
3039 #endif | 3028 #endif |
3040 setAsmCode(); | 3029 setAsmCode(); |
3041 } | 3030 } |
3042 | 3031 |
3043 void doNaked() | 3032 void doNaked() |