00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
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
00023
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
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
00051 prgadr2codemark->clear(1);
00052 }
00053
00054
00055 CodeMark cmark_cnt=1;
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
00065 return(errcnt+1);
00066 }
00067
00068 if(ide->codemark_off)
00069 {
00070
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
00077 prgadr2codemark->insert(RJumpEntry(dadr,cmark_cnt++));
00078 }
00079
00080
00081 adr+=ide->size;
00082 }
00083
00084 TLString itmp;
00085 cmark_cnt=1;
00086 for(PrgAdr adr=0; adr<pfunc->length(); )
00087 {
00088 const INST::DescEntry *ide=INST::Desc(pfunc->InstructionAt(adr));
00089 Assert(ide);
00090
00091
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
00116 char *prg_inst_adr = &pfunc->index(adr+ide->codemark_off) ;
00117 PrgAdr rel_adr=*(PrgAdr*)prg_inst_adr;
00118
00119
00120 *(CodeMark*)prg_inst_adr=(CodeMark)(cmark_cnt++);
00121
00122 itmp=pfunc->DumpInstruction(adr);
00123
00124
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
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
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
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
00293 if(need_info)
00294 {
00295
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
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
00421 fprintf(fp,"info:\n");
00422 if(abi_version)
00423 { fprintf(fp,"\tabiversion %s\n",abi_version.str()); }
00424 fprintf(fp,"\n");
00425
00426
00427 fprintf(fp,"symbols:\n");
00428 if(_WriteSymbolSectionContent(fp))
00429 { ++errcnt; }
00430 fprintf(fp,"\n");
00431
00432
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
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
00470 }
00471
00472 }
00473
00474
00475 #if 0
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
00505 0);
00506
00507 int rv=_DoParseFile(argc>1 ? arg[1] : "parser-test.tasm");
00508
00509 MessageManager::cleanup();
00510 return(rv);
00511 }
00512
00513 #endif