Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

/ray/src/vm/input/tasm/tasm-file.cc

Go to the documentation of this file.
00001 /*
00002  * vm/input/tasm/tasm-file.cc
00003  * 
00004  * VM plaintext assembly input file. 
00005  * 
00006  * Copyright (c) 2004 by Wolfgang Wieser ] wwieser (a) gmx <*> de [ 
00007  * 
00008  * This file may be distributed and/or modified under the terms of the 
00009  * GNU General Public License version 2 as published by the Free Software 
00010  * Foundation. (See COPYING.GPL for details.)
00011  * 
00012  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00013  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00014  * 
00015  */
00016 
00017 #include "tasm-file.h"
00018 #include <lib/serror.h>
00019 #include <lib/message/message.h>
00020 #include <lib/lex/strtreedump.h>
00021 
00022 // NOTE: The parsing routines are in parse.cc. 
00023 //       Only the non-parsing routines go here. 
00024 
00025 
00026 namespace VM
00027 {
00028 
00029 int AssemblerFile_Plaintext::_WriteFunctionProgram(FILE *fp,
00030     ProgramStorage::Function *pfunc)
00031 {
00032     int errcnt=0;
00033     
00034     if(pfunc==slabel_start.pfunc)
00035     {  fprintf(fp,".start:");  }
00036     else if(pfunc==slabel_init.pfunc)
00037     {  fprintf(fp,".init:");  }
00038     else
00039     {  fprintf(fp,"$%d:",(int)pfunc->se->symref);  }
00040     // Be a bit verbose what we dump here...
00041     fprintf(fp,"  # Function %s (type: %s)\n",
00042         pfunc->se->CompleteName().str(),
00043         pfunc->se->ftype.TypeString().str());
00044     
00045     bool free_p2c=!prgadr2codemark;
00046     if(free_p2c)
00047     {  prgadr2codemark=new TLArrayHeap<RJumpEntry,RJumpEntry_Operators>();  }
00048     else
00049     {
00050         // Purge old content to be sure. 
00051         prgadr2codemark->clear(/*keep_memory=*/1);
00052     }
00053     
00054     // First, scan the function for jumps: 
00055     CodeMark cmark_cnt=1;  // Start with 1; the same as below!!
00056     for(PrgAdr adr=0; adr<pfunc->length(); )
00057     {
00058         const INST::DescEntry *ide=INST::Desc(pfunc->InstructionAt(adr));
00059         if(!ide)
00060         {
00061             Error(pfunc->loc,
00062                 "illegal instruction at address 0x%x in \"%s\"",
00063                 (uint)adr,pfunc->se->CompleteName().str());
00064             // No use to go on; we cannto compute the size of the skip. 
00065             return(errcnt+1);
00066         }
00067         
00068         if(ide->codemark_off)
00069         {
00070             // Extract jump address from program memory: 
00071             char *prg_inst_adr = &pfunc->index(adr+ide->codemark_off) ;
00072             PrgAdr rel_adr=*(PrgAdr*)prg_inst_adr;
00073             
00074             PrgAdr dadr = int32(adr)+int32(rel_adr);
00075             
00076             // Put into list: 
00077             prgadr2codemark->insert(RJumpEntry(dadr,cmark_cnt++));
00078         }
00079         
00080         // Skip to next instruction. 
00081         adr+=ide->size;
00082     }
00083     
00084     TLString itmp;
00085     cmark_cnt=1;  // Start with 1; the same as above!!
00086     for(PrgAdr adr=0; adr<pfunc->length(); )
00087     {
00088         const INST::DescEntry *ide=INST::Desc(pfunc->InstructionAt(adr));
00089         Assert(ide);
00090         
00091         // Well, the only thing we must back-convert is codemark labels. 
00092         if(!prgadr2codemark->IsEmpty() && prgadr2codemark->first()->adr<=adr)
00093         {
00094             if(prgadr2codemark->first()->adr<adr)
00095             {
00096                 Error(pfunc->loc,
00097                     "illegal relative jump to address 0x%x in \"%s\"",
00098                     (uint)prgadr2codemark->first()->adr,
00099                     pfunc->se->CompleteName().str());
00100                 prgadr2codemark->PopFirst();
00101                 ++errcnt;
00102             }
00103             else
00104             {
00105                 fprintf(fp,"&0x%x:\n",
00106                     (uint)prgadr2codemark->first()->cmark);
00107                 
00108                 int _unused_ rv=prgadr2codemark->PopFirst();
00109                 Assert(!rv);
00110             }
00111         }
00112         
00113         if(ide->codemark_off)
00114         {
00115             // Temporarily replace relavtive address with CodeMark: 
00116             char *prg_inst_adr = &pfunc->index(adr+ide->codemark_off) ;
00117             PrgAdr rel_adr=*(PrgAdr*)prg_inst_adr;
00118             
00119             // Change program memory. 
00120             *(CodeMark*)prg_inst_adr=(CodeMark)(cmark_cnt++);
00121             
00122             itmp=pfunc->DumpInstruction(adr);
00123             
00124             // Undo change to program memory. 
00125             *(PrgAdr*)prg_inst_adr=(PrgAdr)rel_adr;
00126         }
00127         else
00128         {
00129             itmp=pfunc->DumpInstruction(adr);
00130         }
00131         
00132         fprintf(fp,"\t%s\n",itmp.str());
00133         
00134         // Skip to next instruction. 
00135         adr+=ide->size;
00136     }
00137     
00138     if(!prgadr2codemark->IsEmpty())
00139     {
00140         Error(pfunc->loc,
00141             "%u illegal relative jumps in \"%s\"",
00142             (uint)prgadr2codemark->NElem(),
00143             pfunc->se->CompleteName().str());
00144         prgadr2codemark->PopFirst();
00145         ++errcnt;
00146     }
00147     
00148     if(free_p2c)
00149     {  DELETE(prgadr2codemark);  }
00150     
00151     return(errcnt);
00152 }
00153 
00154 
00155 int AssemblerFile_Plaintext::_MustDumpNamespace(NamespaceInfo *ni)
00156 {
00157     ClassInfo *ci=NULL;
00158     switch(ni->nstype)
00159     {
00160         case NamespaceInfo::NSNamespace:  break;
00161         case NamespaceInfo::NSClass:  ci=static_cast<ClassInfo*>(ni);  break;
00162         default: Assert(0);
00163     }
00164     
00165     bool need_class = (ci && (ci->need_construct || ci->need_cast));
00166     
00167     int need = need_class ? 2 : 0;
00168     if(!need)
00169     {
00170         for(NamespaceInfo *i=ni->down.first(); i; i=i->next)
00171         {
00172             int rv=_MustDumpNamespace(i);
00173             if(rv)
00174             {  need=1;  break;  }
00175         }
00176     }
00177     
00178     if(need<2 && cfg.emit_all_classinfo)  need=2;
00179     else if(need<1 && cfg.emit_all_namespaces)  need=1;
00180     
00181     return(need);
00182 }
00183 
00184 
00185 int AssemblerFile_Plaintext::_WriteSymbols_Recursive(StringTreeDump &out,
00186     NamespaceInfo *ni)
00187 {
00188     int errcnt=0;
00189     
00190     bool has_children = !ni->down.IsEmpty();
00191     int need_info = _MustDumpNamespace(ni);
00192     ClassInfo *ci=NULL;
00193     switch(ni->nstype)
00194     {
00195         case NamespaceInfo::NSNamespace:  break;
00196         case NamespaceInfo::NSClass:  ci=static_cast<ClassInfo*>(ni);  break;
00197         default: Assert(0);
00198     }
00199     
00200     // Dump namespace info (first part) if needed. 
00201     TLString tmp;
00202     if(need_info)
00203     {
00204         if(ni->parent)
00205         {
00206             if(ci)
00207             {  tmp.sprintf("class %d %s\n",
00208                 (int)ci->class_tid,ci->name.str());  }
00209             else
00210             {  tmp.sprintf("namespace %s\n",ni->name.str());  }
00211             out+=tmp;
00212         }
00213         out.AddIndent();
00214     }
00215     
00216     // Dump class info if needed. 
00217     if(need_info>1 && ci)
00218     {
00219         Assert(ci);
00220         
00221         if(ci->base.n())
00222         {
00223             tmp.sprintf("base %u",(uint)ci->base.n());
00224             out+=tmp;
00225             
00226             for(uint32 i=0; i<ci->base.n(); i++)
00227             {
00228                 const ClassInfo::BaseEntry *e=&ci->base[i];
00229                 tmp.sprintf(", %d 0x%x",e->ci->class_tid,(uint)e->off);
00230                 out+=tmp;
00231             }
00232             
00233             out+=";\n";
00234         }
00235         
00236         {
00237             uint32 num_p=0,num_v=0;
00238             for(uint32 i=0; i<ci->membvar.n(); i++)
00239             {
00240                 const ClassInfo::MemberVarEntry *e=&ci->membvar[i];
00241                 if(e->vtype.IsPointerType())  ++num_p;
00242                 else  ++num_v;
00243             }
00244             
00245             tmp.sprintf("size 0x%x %u,%u\n",
00246                 (uint)ci->size,num_p,num_v);
00247             out+=tmp;
00248             
00249             if(num_p || num_v)
00250             {
00251                 out.AddIndent();
00252                 
00253                 for(uint32 i=0; i<ci->membvar.n(); i++)
00254                 {
00255                     const ClassInfo::MemberVarEntry *e=&ci->membvar[i];
00256                     tmp.sprintf("%s 0x%x%s%s\n",
00257                         e->vtype.TypeString().str(),
00258                         (uint)e->off,
00259                         e->name ? ", " : "",
00260                         e->name ? e->name.str() : "");
00261                     out+=tmp;
00262                 }
00263                 
00264                 out.SubIndent();
00265             }
00266             
00267             out+=";\n";
00268         }
00269         
00270         if(ci->nvirtuals)
00271         {
00272             tmp.sprintf("virtual %u\n",(uint)ci->nvirtuals);
00273             out+=tmp;
00274         }
00275         
00276         if(ci->vtable.n())
00277         {
00278             tmp.sprintf("vtable %u",(uint)ci->vtable.n());
00279             out+=tmp;
00280             
00281             for(uint32 i=0; i<ci->vtable.n(); i++)
00282             {
00283                 const ClassInfo::VTableEntry *e=&ci->vtable[i];
00284                 tmp.sprintf(" $%d",(int)e->se->symref);
00285                 out+=tmp;
00286             }
00287             
00288             out+=";\n";
00289         }
00290     }
00291     
00292     // Dump namespace info (second part) if needed. 
00293     if(need_info)
00294     {
00295         // Recurse: 
00296         if(has_children)
00297         {
00298             tmp.deref();
00299             for(NamespaceInfo *i=ni->down.first(); i; i=i->next)
00300             {  _WriteSymbols_Recursive(out,i);  }
00301         }
00302         
00303         if(!ni->symbol.IsEmpty())
00304         {
00305             out+="symbols\n";
00306             out.AddIndent();
00307         }
00308         for(NamespaceInfo::SymbolList::Iterator i(ni->symbol); i; i++)
00309         {
00310             const NamespaceInfo::SymbolEntryE *se=*i;
00311             
00312             switch(se->extid)
00313             {
00314                 case NamespaceInfo::SymbolEntryE::ExtFunction:
00315                 {
00316                     const char *ftype_base=NULL;
00317                     switch(se->ftype.id)
00318                     {
00319                         case FuncType::Function:  ftype_base="function";  break;
00320                         case FuncType::Method:    ftype_base="method";    break;
00321                         case FuncType::VMethod:   ftype_base="vmethod";   break;
00322                         //case FuncType::Unknown:   ftype_base="???";  break;
00323                         default: Assert(0);
00324                     }
00325 
00326                     tmp.sprintf("%s%s $%d %s\n",
00327                         se->ftype.exported ? "" : "s",
00328                         ftype_base,
00329                         (int)se->symref,
00330                         se->name.str());
00331                     out+=tmp;
00332                 } break;
00333                 case NamespaceInfo::SymbolEntryE::ExtVariable:
00334                 {
00335                     tmp.sprintf("%s $%d %s\n",
00336                         se->vtype.TypeString().str(),
00337                         (int)se->symref,
00338                         se->name.str());
00339                     out+=tmp;
00340                 } break;
00341                 default: Assert(0);
00342             }
00343         }
00344         if(!ni->symbol.IsEmpty())
00345         {
00346             out.SubIndent();
00347             out+=";\n";
00348         }
00349         
00350         out.SubIndent();
00351         if(ni->parent)
00352         {  out+=";\n";  }
00353     }
00354     
00355     return(errcnt);
00356 }
00357 
00358 
00359 int AssemblerFile_Plaintext::_WriteSymbols_Global(StringTreeDump &out,
00360     _GlobVars *gvar,char which)
00361 {
00362     TLString tmp;
00363     tmp.sprintf("%cglobal 0x%x\n",which,(uint)gvar->size);
00364     out+=tmp;
00365     
00366     if(!gvar->globvarq.IsEmpty())
00367     {
00368         out.AddIndent();
00369         
00370         for(GlobalVarList::Iterator i(gvar->globvarq); i; i++)
00371         {
00372             const GlobalVarEntry *e=(*i);
00373             tmp.sprintf("%s 0x%x $%d\n",
00374                 e->vtype.TypeString().str(),
00375                 (uint)e->off,
00376                 (int)e->se->symref);
00377             out+=tmp;
00378         }
00379         
00380         out.SubIndent();
00381     }
00382     
00383     out+=";\n";
00384     
00385     return(0);
00386 }
00387 
00388 
00389 int AssemblerFile_Plaintext::_WriteSymbolSectionContent(FILE *fp)
00390 {
00391     int errcnt=0;
00392     
00393     StringTreeDump out;
00394     
00395     if(_WriteSymbols_Recursive(out,nspc_root))
00396     {  ++errcnt;  }
00397     
00398     out.AddIndent();
00399     if(_WriteSymbols_Global(out,&gvar_v,'v'))  ++errcnt;
00400     if(_WriteSymbols_Global(out,&gvar_p,'p'))  ++errcnt;
00401     out.SubIndent();
00402     
00403     out.write(fp,1,'\t');
00404     
00405     return(errcnt);
00406 }
00407 
00408 
00409 int AssemblerFile_Plaintext::WriteFile(const TLString &fname,SError &error)
00410 {
00411     FILE *fp=fopen(fname.str(),"w");
00412     if(!fp)
00413     {  error=SError("error blah blah...",1);  return(-2);  }
00414     
00415     int errcnt=0;
00416     
00417     prgadr2codemark=new TLArrayHeap<RJumpEntry,RJumpEntry_Operators>();
00418     
00419     do {
00420         // Write info section. 
00421         fprintf(fp,"info:\n");
00422         if(abi_version)
00423         {  fprintf(fp,"\tabiversion %s\n",abi_version.str());  }
00424         fprintf(fp,"\n");
00425         
00426         // Write symbols section. 
00427         fprintf(fp,"symbols:\n");
00428         if(_WriteSymbolSectionContent(fp))
00429         {  ++errcnt;  }
00430         fprintf(fp,"\n");
00431         
00432         // Write program section. 
00433         fprintf(fp,"program:\n");
00434         for(ProgramStorage::Function *pfunc=program.FirstFunction();
00435             pfunc; pfunc=pfunc->next)
00436         {
00437             if(_WriteFunctionProgram(fp,pfunc))
00438             {  ++errcnt;  }
00439             if(pfunc->next)
00440             {  fprintf(fp,"\n");  }
00441         }
00442         
00443         fprintf(fp,"\n#EOF\n");
00444     } while(0);
00445     
00446     // Clean up: 
00447     DELETE(prgadr2codemark);
00448     
00449     fclose(fp);
00450     return(errcnt);
00451 }
00452 
00453 
00454 AssemblerFile_Plaintext::AssemblerFile_Plaintext() : 
00455     AssemblerFile(),
00456     scan(),
00457     n_errors(0),
00458     codemark2prgadr(),
00459     prgadr2codemark(NULL),
00460     tok(NULL)
00461 {
00462     
00463 }
00464 
00465 AssemblerFile_Plaintext::~AssemblerFile_Plaintext()
00466 {
00467     DELETE(prgadr2codemark);
00468     
00469     // codemark2prgadr tidies up itself. 
00470 }
00471 
00472 }  // end of namespace VM
00473 
00474 
00475 #if 0  /* small test program */
00476 
00477 #include <lib/message/manager.h>
00478 #include <lib/message/handler_console.h>
00479 
00480 
00481 static int _DoParseFile(const char *file)
00482 {
00483     VM::AssemblerFile_Plaintext asmfile;
00484     SError error;
00485     
00486     int rv=asmfile.ParseFile(file,error);
00487     if(rv)
00488     {
00489         if(error)
00490         {  Error("parsing %s: %s",file,error.msg().str());  }
00491         else
00492         {  Error("%d lexer/parser errors",rv);  }
00493         return(1);
00494     }
00495     
00496     return(0);
00497 }
00498 
00499 int main(int argc,char **arg)
00500 {
00501     MessageManager::init();
00502     MessageHandler_Console cons_hdl(
00503         Message::MTAll,
00504         //Message::MTAllNonDebug,
00505         /*use_color=*/0);
00506     
00507     int rv=_DoParseFile(argc>1 ? arg[1] : "parser-test.tasm");
00508     
00509     MessageManager::cleanup();
00510     return(rv);
00511 }
00512 
00513 #endif

Generated on Sat Feb 19 22:33:47 2005 for Ray by doxygen 1.3.5