00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "c_breeze.h"
00040 #include "arch_info_parser.h"
00041 #include "lirutil.h"
00042
00043
00044 #define PARSE_ERROR CBZFAIL
00045
00046 arch_info_parser::arch_info_parser()
00047 {
00048
00049 _initialized = false;
00050 _pSpecFile = NULL;
00051 _lastChar = NO_CHAR;
00052 _wasNewLine = false;
00053 }
00054
00055 arch_info_parser::~arch_info_parser()
00056 {
00057 }
00058
00059 void arch_info_parser::init_parser()
00060 {
00061
00062 if ( _initialized )
00063 return;
00064
00066
00067
00068 int i;
00069
00070
00071 for ( i = 0; i < 256; ++i )
00072 _charClass[i] = SPECIAL;
00073
00074
00075 for ( i = '0'; i <= '9'; ++i )
00076 _charClass[i] = ALPHANUM;
00077 for ( i = 'a'; i <= 'z'; ++i )
00078 _charClass[i] = ALPHANUM;
00079 for ( i = 'A'; i <= 'Z'; ++i )
00080 _charClass[i] = ALPHANUM;
00081
00082
00083 _charClass[' '] = WS;
00084 _charClass['\t'] = WS;
00085 _charClass['\n'] = LINEBREAK;
00086
00088
00089
00090
00091 _thingsToParse.push_back(thing_to_parse("ArchName", &arch_info::_archName));
00092 _thingsToParse.push_back( thing_to_parse("AsmLineComment",
00093 &arch_info::_asmLineComment));
00094 _thingsToParse.push_back( thing_to_parse( "AsmRegPrefixAdd",
00095 &arch_info::_asmRegPrefixAdd ) );
00096 _thingsToParse.push_back( thing_to_parse("AsmRegPrefixRemove",
00097 &arch_info::_asmRegPrefixRemove ) );
00098 _thingsToParse.push_back( thing_to_parse( "AsmConstPrefix",
00099 &arch_info::_asmConstPrefix ) );
00100
00101
00102 _thingsToParse.push_back( thing_to_parse( "RegsAll",
00103 &arch_info::_regsAll, true ) );
00104 _thingsToParse.push_back( thing_to_parse( "RegsGpr",
00105 &arch_info::_regsGpr ) );
00106 _thingsToParse.push_back( thing_to_parse( "RegsFpr",
00107 &arch_info::_regsFpr ) );
00108 _thingsToParse.push_back( thing_to_parse( "RegSp",
00109 &arch_info::_regSp ) );
00110 _thingsToParse.push_back( thing_to_parse( "RegFp",
00111 &arch_info::_regFp ) );
00112 _thingsToParse.push_back( thing_to_parse( "RegsParamFixed",
00113 &arch_info::_regsParamFixed ) );
00114 _thingsToParse.push_back( thing_to_parse( "RegsParamFloat",
00115 &arch_info::_regsParamFloat ) );
00116 _thingsToParse.push_back( thing_to_parse( "RegRetvalFixed",
00117 &arch_info::_regRetvalFixed ) );
00118 _thingsToParse.push_back( thing_to_parse( "RegRetvalFloat",
00119 &arch_info::_regRetvalFloat ) );
00120 _thingsToParse.push_back( thing_to_parse( "RegsCallerSave",
00121 &arch_info::_regsCallerSave ) );
00122 _thingsToParse.push_back( thing_to_parse( "RegsCalleeSave",
00123 &arch_info::_regsCalleeSave ) );
00124 _thingsToParse.push_back( thing_to_parse( "RegDataTypeGpr",
00125 &arch_info::_regDataTypeGpr ) );
00126 _thingsToParse.push_back( thing_to_parse( "RegDataTypeFpr",
00127 &arch_info::_regDataTypeFpr ) );
00128
00129
00130 _thingsToParse.push_back( thing_to_parse( "DataSizeShort",
00131 &arch_info::_dataSizeShort ) );
00132 _thingsToParse.push_back( thing_to_parse( "DataSizeInt",
00133 &arch_info::_dataSizeInt ) );
00134 _thingsToParse.push_back( thing_to_parse( "DataSizeLong",
00135 &arch_info::_dataSizeLong ) );
00136 _thingsToParse.push_back( thing_to_parse( "DataSizeFloat",
00137 &arch_info::_dataSizeFloat ) );
00138 _thingsToParse.push_back( thing_to_parse( "DataSizeDouble",
00139 &arch_info::_dataSizeDouble ) );
00140 _thingsToParse.push_back( thing_to_parse( "DataSizePtr",
00141 &arch_info::_dataSizePtr ) );
00142
00143
00144 _thingsToParse.push_back( thing_to_parse( "DataAlignChar",
00145 &arch_info::_dataAlignChar ) );
00146 _thingsToParse.push_back( thing_to_parse( "DataAlignShort",
00147 &arch_info::_dataAlignShort ) );
00148 _thingsToParse.push_back( thing_to_parse( "DataAlignInt",
00149 &arch_info::_dataAlignInt ) );
00150 _thingsToParse.push_back( thing_to_parse( "DataAlignLong",
00151 &arch_info::_dataAlignLong ) );
00152 _thingsToParse.push_back( thing_to_parse( "DataAlignFloat",
00153 &arch_info::_dataAlignFloat ) );
00154 _thingsToParse.push_back( thing_to_parse( "DataAlignDouble",
00155 &arch_info::_dataAlignDouble ) );
00156 _thingsToParse.push_back( thing_to_parse( "DataAlignPtr",
00157 &arch_info::_dataAlignPtr ) );
00158
00159
00160 _thingsToParse.push_back( thing_to_parse( "StackFrameMinSize",
00161 &arch_info::_stackFrameMinSize ) );
00162 _thingsToParse.push_back( thing_to_parse( "StackExtraTop",
00163 &arch_info::_stackExtraTop ) );
00164 _thingsToParse.push_back( thing_to_parse( "StackExtraBottom",
00165 &arch_info::_stackExtraBottom ) );
00166 _thingsToParse.push_back( thing_to_parse( "StackAlign",
00167 &arch_info::_stackAlign ) );
00168 _thingsToParse.push_back( thing_to_parse("StackFormalsOffset",
00169 &arch_info::_stackFormalsOffset ) );
00170
00171
00172 _thingsToParse.push_back( thing_to_parse( "LirEmulate3Address",
00173 &arch_info::_emulate3Address ) );
00174 _thingsToParse.push_back( thing_to_parse( "Lir2Asm",
00175 &arch_info::_Lir2Asm_records ) );
00176
00178
00179
00180
00181 #define MNEMONIC( mnemonic ) \
00182 { \
00183 string temp( #mnemonic ); \
00184 cbz_util::string_to_lower( temp ); \
00185 _mnemonicMap[ temp ] = mn_##mnemonic; \
00186 }
00187 MNEMONIC( NOP );
00188 MNEMONIC( ConvertType );
00189 MNEMONIC( Load );
00190 MNEMONIC( LoadImmediate );
00191 MNEMONIC( LoadStatic );
00192 MNEMONIC( Store );
00193 MNEMONIC( StoreStatic );
00194 MNEMONIC( GetEffectiveAddr );
00195 MNEMONIC( GetGlobalAddr );
00196 MNEMONIC( Move );
00197 MNEMONIC( Add );
00198 MNEMONIC( Sub );
00199 MNEMONIC( Mul );
00200 MNEMONIC( Div );
00201 MNEMONIC( Mod );
00202 MNEMONIC( Neg );
00203 MNEMONIC( BitwiseOR );
00204 MNEMONIC( BitwiseAND );
00205 MNEMONIC( BitwiseXOR );
00206 MNEMONIC( BitwiseNOT );
00207 MNEMONIC( BitwiseShiftLeft );
00208 MNEMONIC( BitwiseShiftRight );
00209 MNEMONIC( BitwiseRotateRight );
00210 MNEMONIC( BitwiseRotateLeft );
00211 MNEMONIC( Compare );
00212 MNEMONIC( BranchEQ );
00213 MNEMONIC( BranchNE );
00214 MNEMONIC( BranchLT );
00215 MNEMONIC( BranchLE );
00216 MNEMONIC( BranchGT );
00217 MNEMONIC( BranchGE );
00218 MNEMONIC( Jmp );
00219 MNEMONIC( Call );
00220 MNEMONIC( IndirectCall );
00221 MNEMONIC( Return );
00222 MNEMONIC( Label );
00223 MNEMONIC( DeclLocal );
00224 MNEMONIC( DeclGlobal );
00225 MNEMONIC( StaticDataString );
00226 MNEMONIC( StaticDataLong );
00227 MNEMONIC( StaticDataInt );
00228 MNEMONIC( StaticDataShort );
00229 MNEMONIC( StaticDataChar );
00230 MNEMONIC( StaticDataSingle );
00231 MNEMONIC( StaticDataDouble );
00232 MNEMONIC( StaticDataZero );
00233 MNEMONIC( StaticDataUninit );
00234 MNEMONIC( BeginProc );
00235 MNEMONIC( EndProc );
00236 MNEMONIC( BeginUnit );
00237 MNEMONIC( EndUnit );
00238 #undef MNEMONIC
00239
00241
00242
00243
00244 #define VARTYPE( vartype, nodeType ) \
00245 { \
00246 string temp( #vartype ); \
00247 cbz_util::string_to_lower( temp ); \
00248 _varTypeMap[ temp ] = nodeType; \
00249 }
00250 VARTYPE( char, new primNode(typeNode::NONE, basic_type::SChar) );
00251 VARTYPE( uchar, new primNode(typeNode::NONE, basic_type::UChar) );
00252 VARTYPE( short, new primNode(typeNode::NONE, basic_type::SShort) );
00253 VARTYPE( ushort, new primNode(typeNode::NONE, basic_type::UShort) );
00254 VARTYPE( int, new primNode(typeNode::NONE, basic_type::SInt) );
00255 VARTYPE( uint, new primNode(typeNode::NONE, basic_type::UInt) );
00256 VARTYPE( long, new primNode(typeNode::NONE, basic_type::SLong) );
00257 VARTYPE( ulong, new primNode(typeNode::NONE, basic_type::ULong) );
00258 VARTYPE( float, new primNode(typeNode::NONE, basic_type::Float) );
00259 VARTYPE( double, new primNode(typeNode::NONE, basic_type::Double) );
00260 VARTYPE( pointer, LirUtil::newVoidPtr() );
00261 #undef VARTYPE
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274 _initialized = true;
00275 }
00276
00277 bool
00278 arch_info_parser::parse( const char * pFileName, arch_info * pArchInfo )
00279 {
00280
00281 _pArchInfo = pArchInfo;
00282 init_parser();
00283
00284
00285 _pSpecFile = fopen( pFileName, "rt" );
00286 if ( ! _pSpecFile ) {
00287 cerr << "ERROR: Can't load '" << pFileName << "' for reading." << endl;
00288 return false;
00289 }
00290
00291
00292 _lastChar = NO_CHAR;
00293 _currentLine = 1;
00294
00295
00296 char c;
00297 while ( (c = peek_char(true)) != EOF && c == '\n' )
00298 get_char();
00299
00300
00301 string keyName;
00302 while ( read_string( keyName ) ) {
00303
00304 string keyNameLower( keyName );
00305 cbz_util::string_to_lower( keyNameLower );
00306
00307
00308 size_t sz = _thingsToParse.size();
00309 bool found = false;
00310 for ( int i = 0; i < (int)sz; ++i ) {
00311
00312 if ( _thingsToParse[i]._keyName == keyNameLower ) {
00313 thing_to_parse & parseThing = _thingsToParse[i];
00314
00315
00316 bool res;
00317 switch ( parseThing._parseType )
00318 {
00319 case type_reg:
00320 res = parse_reg_item(keyName, parseThing._data._reg );
00321 break;
00322 case type_reg_list:
00323 res = parse_reg_list_item(keyName, parseThing._data._regList,
00324 parseThing._regIsMasterList );
00325 break;
00326 case type_string:
00327 res = parse_string_item(keyName, parseThing._data._string );
00328 break;
00329 case type_integer:
00330 res = parse_integer_item(keyName, parseThing._data._int );
00331 break;
00332 case type_boolean:
00333 res = parse_bool_item(keyName, parseThing._data._bool );
00334 break;
00335 case type_vartype:
00336 res = parse_vartype_item(keyName, parseThing._data._vartype );
00337 break;
00338 case type_Lir2Asm:
00339 res = parse_Lir2Asm_item(keyName, parseThing._data._Lir2AsmList );
00340 break;
00341 default:
00342 assert( false );
00343 break;
00344 }
00345
00346
00347 if ( ! res )
00348 return false;
00349
00350
00351 found = true;
00352 break;
00353 }
00354 }
00355
00356
00357 if ( ! found )
00358 PARSE_ERROR( ("unrecognized key name '%s'", keyName.c_str()) );
00359
00360
00361 while ( (c = peek_char(true)) != EOF && c == '\n' )
00362 get_char();
00363 }
00364
00365 return true;
00366 }
00367
00368 char
00369 arch_info_parser::get_char( bool skipWhitespace ) {
00370 char c;
00371
00372
00373 if ( _lastChar == NO_CHAR
00374 || (skipWhitespace && _charClass[_lastChar] == WS) )
00375 peek_char( skipWhitespace );
00376
00377
00378 c = (char)_lastChar;
00379 if ( _lastChar != EOF )
00380 _lastChar = NO_CHAR;
00381
00382 return c;
00383 }
00384
00385 char
00386 arch_info_parser::peek_char( bool skipWhitespace ) {
00387
00388 while ( _lastChar != EOF
00389 && (_lastChar == NO_CHAR
00390 || (skipWhitespace && _charClass[_lastChar] == WS)) ) {
00391 char ch = do_getc();
00392 char ch2;
00393 switch ( ch )
00394 {
00395 case EOF:
00396
00397 _lastChar = EOF;
00398 break;
00399
00400 case '/':
00401
00402 ch2 = do_getc();
00403 if ( ch2 == '*' ) {
00404
00405 char ch3;
00406 while ( ch2 != EOF ) {
00407
00408 ch2 = do_getc();
00409 if ( ch2 != '*' )
00410 continue;
00411
00412
00413 ch3 = do_getc();
00414 if ( ch3 == '/' )
00415 break;
00416
00417
00418 do_ungetc( ch3 );
00419 }
00420
00421
00422 assert( ch2 == EOF || ch3 == '/' );
00423
00424
00425 continue;
00426 } else if ( ch2 != '/' ) {
00427
00428
00429 do_ungetc( ch2 );
00430 _lastChar = ch;
00431 break;
00432 }
00433
00434
00435
00436
00437 case '#':
00438
00439 while ( ((ch2 = do_getc()) != EOF) && ch2 != '\n');
00440
00441
00442 assert( ch2 == EOF || ch2 == '\n' );
00443
00444
00445 continue;
00446
00447 case '\\':
00448
00449 ch2 = do_getc();
00450 if ( ch2 == '#' ) {
00451
00452 _lastChar = ch2;
00453 continue;
00454 } else {
00455
00456 do_ungetc( ch2 );
00457 _lastChar = ch;
00458 continue;
00459 }
00460
00461 break;
00462
00463 default:
00464
00465 _lastChar = ch;
00466 break;
00467 }
00468 }
00469 return _lastChar;
00470 }
00471
00472 char
00473 arch_info_parser::do_getc() {
00474 _wasNewLine = false;
00475
00476
00477 char c = fgetc( _pSpecFile );
00478
00479
00480 if ( c == '\\' ) {
00481
00482 char c2 = fgetc( _pSpecFile );
00483 if ( c2 == '\n' ) {
00484
00485 _currentLine++;
00486 return do_getc();
00487 } else {
00488
00489 ungetc( c2, _pSpecFile );
00490 return c;
00491 }
00492 } else if ( c == '\n' ) {
00493 _currentLine++;
00494 _wasNewLine = true;
00495 }
00496
00497 return c;
00498 }
00499
00500 void
00501 arch_info_parser::do_ungetc( char c ) {
00502
00503 ungetc( c, _pSpecFile );
00504
00505
00506 if ( _wasNewLine ) {
00507 _wasNewLine = false;
00508 _currentLine--;
00509 }
00510 }
00511
00512 bool
00513 arch_info_parser::read_string( string & stringOut, bool readAnyChars,
00514 bool skipLeadingNewlines ) {
00515
00516 stringOut.clear();
00517
00518 char c;
00519
00520
00521 if ( skipLeadingNewlines )
00522 while ( (c = peek_char( true )) != EOF && c == '\n' )
00523 get_char();
00524
00525
00526 c = peek_char( true );
00527 while ( c != EOF
00528 && c != '\n'
00529 && (readAnyChars || _charClass[c] == ALPHANUM) ) {
00530
00531 stringOut.append( 1, c );
00532 get_char();
00533 c = peek_char();
00534 }
00535
00536
00537 return (! stringOut.empty());
00538 }
00539
00540 bool
00541 arch_info_parser::parse_reg_item( string keyName, reg_info_ptr toRead ) {
00542
00543 char c = get_char( true );
00544 if ( c != '=' )
00545 PARSE_ERROR( ("expected '=' after key '%s'", keyName.c_str()) );
00546
00547 c = get_char( true );
00548
00549
00550 if ( c == '\n' )
00551 return true;
00552
00553
00554 if ( c != '@' )
00555 PARSE_ERROR( ("expected '@' preceding register name") );
00556
00557
00558 if ( peek_char( true ) == '\n' )
00559 return true;
00560
00561
00562 string regName;
00563 if ( !read_string( regName ) )
00564 PARSE_ERROR( ("expected register name after '@'") );
00565
00566
00567 arch_info::register_info * info;
00568 if ( ! _pArchInfo->find_register_info( regName.c_str(), info ) )
00569 PARSE_ERROR( ("register '%s' is undefined - is it missing from the "
00570 "RegsAll list?", regName.c_str()) );
00571
00572
00573 _pArchInfo->*toRead = info;
00574
00575
00576 c = get_char( true );
00577 if ( c != '\n' )
00578 PARSE_ERROR( ("expected newline after register name", regName.c_str()) );
00579
00580 return true;
00581 }
00582
00583 bool
00584 arch_info_parser::parse_reg_list_item( string keyName,
00585 reg_info_list_ptr toRead,
00586 bool isMasterList, bool allowTokens ) {
00587
00588 (_pArchInfo->*toRead).empty();
00589
00590
00591 assert( ! (isMasterList && allowTokens) );
00592
00593 char c;
00594
00595
00596 c = get_char( true );
00597 if ( c != '=' )
00598 PARSE_ERROR( ("expected '=' after key '%s'", keyName.c_str()) );
00599
00600
00601 c = get_char( true );
00602 while ( c == '@' || (allowTokens && c == '$') ) {
00603
00604 string regName;
00605 if ( !read_string( regName ) )
00606 PARSE_ERROR( ("expected register name after '%c'", c) );
00607
00608
00609 if ( isMasterList ) {
00610
00611 arch_info::register_info * info = new arch_info::register_info;
00612 info->_id = _pArchInfo->_nextRegId++;
00613 info->_name = regName;
00614 assert( (_pArchInfo->*toRead).size() == info->_id );
00615 (_pArchInfo->*toRead).push_back( info );
00616
00617
00618 _pArchInfo->_regMap[ regName ] = info;
00619 } else {
00620
00621 arch_info::register_info * info;
00622 if ( ! _pArchInfo->find_register_info( regName.c_str(), info ) )
00623 PARSE_ERROR( ("register '%s' is undefined - is it missing from the "
00624 "RegsAll list?", regName.c_str()) );
00625
00626
00627 (_pArchInfo->*toRead).push_back( info );
00628 }
00629
00630
00631 c = get_char( true );
00632 }
00633
00634
00635 if ( c != '\n' )
00636 PARSE_ERROR( ("after '=', expected register list followed by newline") );
00637
00638 return true;
00639 }
00640
00641 bool
00642 arch_info_parser::parse_string_item( string keyName, string_ptr toRead ) {
00643
00644 char c = get_char( true );
00645 if ( c != '=' )
00646 PARSE_ERROR( ("expected '=' after key '%s'", keyName.c_str()) );
00647
00648
00649 if ( peek_char( true ) == '\n' )
00650 return true;
00651
00652
00653 string str;
00654 c = get_char( true );
00655 while ( c != EOF && c != '\n' ) {
00656
00657 str.append( 1, c );
00658 c = get_char( false );
00659 }
00660
00661
00662 _pArchInfo->*toRead = str;
00663
00664 return true;
00665 }
00666
00667 bool
00668 arch_info_parser::parse_integer_item( string keyName, int_ptr toRead ) {
00669
00670 char c = get_char( true );
00671 if ( c != '=' )
00672 PARSE_ERROR( ("expected '=' after key '%s'", keyName.c_str()) );
00673
00674
00675 if ( peek_char( true ) == '\n' )
00676 return true;
00677
00678
00679 string str;
00680 if ( ! read_string( str ) )
00681 PARSE_ERROR( ("expected numeric constant after '='") );
00682
00683
00684 int value = atoi( str.c_str() );
00685 if ( value == 0 && str.find_first_not_of( "0123456789" ) != -1 )
00686 PARSE_ERROR( ("expected numeric constant after '='") );
00687
00688
00689 c = get_char( true );
00690 if ( c != '\n' )
00691 PARSE_ERROR( ("expected newline after integer constant") );
00692
00693
00694 _pArchInfo->*toRead = value;
00695
00696 return true;
00697 }
00698
00699 bool
00700 arch_info_parser::parse_bool_item( string keyName, bool_ptr toRead ) {
00701
00702 char c = get_char( true );
00703 if ( c != '=' )
00704 PARSE_ERROR( ("expected '=' after key '%s'", keyName.c_str()) );
00705
00706
00707 string str;
00708 if ( ! read_string( str ) )
00709 PARSE_ERROR( ("expected boolean value after '='") );
00710
00711
00712 cbz_util::string_to_lower( str );
00713 if ( str == "true" || str == "yes" )
00714 _pArchInfo->*toRead = true;
00715 else if ( str == "false" || str == "no" )
00716 _pArchInfo->*toRead = false;
00717 else
00718 PARSE_ERROR( ("expected 'true'/'yes' or 'false'/'no' after '='") );
00719
00720
00721 c = get_char( true );
00722 if ( c != '\n' )
00723 PARSE_ERROR( ("expected newline after integer constant") );
00724
00725 return true;
00726 }
00727
00728 bool
00729 arch_info_parser::parse_vartype_item( string keyName, vartype_ptr toRead ) {
00730
00731 char c = get_char( true );
00732 if ( c != '=' )
00733 PARSE_ERROR( ("expected '=' after key '%s'", keyName.c_str()) );
00734
00735
00736 string typeStr;
00737 if ( ! read_string( typeStr ) )
00738 PARSE_ERROR( ("expected data type after '='") );
00739
00740
00741 cbz_util::string_to_lower( typeStr );
00742 vartype_map::iterator it = _varTypeMap.find( typeStr );
00743 if ( it == _varTypeMap.end() )
00744 PARSE_ERROR( ("unrecognized variable type '%s'", typeStr.c_str()) );
00745
00746
00747 c = get_char( true );
00748 if ( c != '\n' )
00749 PARSE_ERROR( ("expected newline after integer constant") );
00750
00751
00752 _pArchInfo->*toRead = (*it).second;
00753
00754 return true;
00755 }
00756
00757 bool
00758 arch_info_parser::parse_Lir2Asm_item( string keyName,
00759 Lir2Asm_list_ptr toAppend ) {
00760
00761 char c;
00762 while ( (c = get_char( true )) == '\n' );
00763
00764
00765 if ( c != '[' )
00766 PARSE_ERROR( ("expected '[' after '%s'", keyName.c_str()) );
00767
00768
00769 bool hasCode = false;
00770 arch_info::Lir2Asm lir2asm;
00771 lir2asm.reset();
00772 string keyStr;
00773 while ( read_string( keyStr, false, true ) ) {
00774 string keyStrLower = keyStr;
00775 cbz_util::string_to_lower( keyStrLower );
00776 if ( keyStrLower == "lir" ) {
00777
00778 _pArchInfo->_tempParseString.clear();
00779 if ( ! parse_string_item( "lir", &arch_info::_tempParseString ) )
00780 return false;
00781 string mnemonicStr = _pArchInfo->_tempParseString;
00782 _pArchInfo->_tempParseString.clear();
00783
00784
00785 string tempStr( mnemonicStr );
00786 cbz_util::string_to_lower( tempStr );
00787 mnemonic_map::iterator it = _mnemonicMap.find( tempStr );
00788 if ( it == _mnemonicMap.end() )
00789 PARSE_ERROR( ("unrecognized LIR instruction '%s'",
00790 mnemonicStr.c_str()) );
00791
00792
00793 lir2asm._lirInstTypes.push_back( (*it).second );
00794 } else if ( keyStrLower == "datatype" ) {
00795
00796 _pArchInfo->_tempParseString.clear();
00797 if ( ! parse_string_item( "datatype", &arch_info::_tempParseString ) )
00798 return false;
00799 string typeStr = _pArchInfo->_tempParseString;
00800 _pArchInfo->_tempParseString.clear();
00801
00802
00803 string tempStr( typeStr );
00804 cbz_util::string_to_lower( tempStr );
00805 vartype_map::iterator it = _varTypeMap.find( tempStr );
00806 if ( it == _varTypeMap.end() )
00807 PARSE_ERROR( ("unrecognized variable type '%s'", typeStr.c_str()) );
00808
00809
00810 lir2asm._dataTypes.push_back( (*it).second );
00811 } else if ( keyStrLower == "converttotype" ) {
00812
00813 _pArchInfo->_tempParseString.clear();
00814 if ( ! parse_string_item( "converttotype",
00815 &arch_info::_tempParseString ) )
00816 return false;
00817 string typeStr = _pArchInfo->_tempParseString;
00818 _pArchInfo->_tempParseString.clear();
00819
00820
00821 string tempStr( typeStr );
00822 cbz_util::string_to_lower( tempStr );
00823 vartype_map::iterator it = _varTypeMap.find( tempStr );
00824 if ( it == _varTypeMap.end() )
00825 PARSE_ERROR( ("unrecognized variable type '%s'", typeStr.c_str()) );
00826
00827
00828 lir2asm._convertToTypes.push_back( (*it).second );
00829 } else if ( keyStrLower == "kill" ) {
00830
00831 _pArchInfo->_tempRegList.clear();
00832 if ( ! parse_reg_list_item( "kill", &arch_info::_tempRegList, false,
00833 true ) )
00834 return false;
00835
00836
00837 cbz_util::vector_copy( _pArchInfo->_tempRegList, lir2asm._killRegs );
00838 _pArchInfo->_tempRegList.clear();
00839 } else if ( keyStrLower == "immed" ) {
00840
00841 _pArchInfo->_tempBool = false;
00842 if ( ! parse_bool_item( "immed", &arch_info::_tempBool ) )
00843 return false;
00844 lir2asm._immed = _pArchInfo->_tempBool ?
00845 arch_info::Lir2Asm::Immed_Yes :
00846 arch_info::Lir2Asm::Immed_No;
00847 } else if ( keyStrLower == "code" ) {
00848 char c;
00849
00850
00851 hasCode = true;
00852
00853
00854 while ( (c = peek_char( true )) == '\n' || _charClass[c] == WS )
00855 get_char();
00856
00857
00858 get_char();
00859 if ( c == '=' ) {
00860
00861 string str;
00862 if ( read_string( str, true ) ) {
00863
00864 lir2asm._codeTemplate.push_back( str );
00865 }
00866
00867
00868 c = get_char( true );
00869 assert( c == EOF || c == '\n' );
00870 get_char();
00871 } else if ( c == '{' ) {
00872
00873 while ( 1 ) {
00874
00875 string line;
00876 c = get_char( true );
00877 while ( c != EOF && c != '\n' && c != '}' ) {
00878 line += c;
00879 c = get_char();
00880 }
00881
00882
00883 if ( ! line.empty() )
00884 lir2asm._codeTemplate.push_back( line );
00885
00886
00887 if ( c == EOF || c == '}' )
00888 break;
00889 }
00890 } else {
00891
00892 PARSE_ERROR( ("missing '=' or '{' after 'code'") );
00893 }
00894 } else {
00895
00896 PARSE_ERROR( ("unrecognized key string '%s'.", keyStr.c_str()) );
00897 }
00898 }
00899
00900
00901 while ( (c = get_char( true )) == '\n' );
00902 if ( c != ']' )
00903 PARSE_ERROR( ("expected ']' after arch_info::Lir2Asm record") );
00904
00905
00906 if ( ! hasCode )
00907 return true;
00908
00909
00910 _pArchInfo->_Lir2Asm_records.push_back( lir2asm );
00911 int addpos = (int)(_pArchInfo->_Lir2Asm_records.size()) - 1;
00912 assert( addpos >= 0 );
00913
00914
00915
00916 size_t sz = lir2asm._lirInstTypes.size();
00917 for ( int i = 0; i < (int)sz; ++i ) {
00918
00919 arch_info::map_menmonic_to_record_set::iterator it =
00920 _pArchInfo->_Lir2Asm_mnemonicLookup.find( lir2asm._lirInstTypes[i] );
00921 if ( it == _pArchInfo->_Lir2Asm_mnemonicLookup.end() ) {
00922 arch_info::map_menmonic_to_record_set::value_type toInsert( lir2asm._lirInstTypes[i], vector<int>() );
00923 it = _pArchInfo->_Lir2Asm_mnemonicLookup.insert( toInsert ).first;
00924 }
00925
00926
00927 it->second.push_back( addpos );
00928 }
00929
00930 return true;
00931 }
00932