00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "linker.h"
00018 #include <lib/message/message.h>
00019 #include "classinfo.h"
00020 #include <lib/tl/sort.h>
00021 #include <lib/tl/binsearch.h>
00022 #include <lib/lex/strtreedump.h>
00023
00024
00025 namespace VM
00026 {
00027
00028 NamespaceInfo::SymbolEntryE *VMLinker::SymbolProvideMap::AddNode(
00029 NamespaceInfo::SymbolEntryE *s)
00030 {
00031 NamespaceInfo::SymbolEntryE *known=NULL;
00032 if(map.store(s,0,&known))
00033 {
00034 Assert(known);
00035 return(known);
00036 }
00037 return(NULL);
00038 }
00039
00040
00041
00042
00043 struct MemberVarEntryOffsetOperators
00044 {
00045 static inline bool lt(ClassInfo::MemberVarEntry const &a,Offset const &b)
00046 { return(a.off<b); }
00047 static inline bool eq(ClassInfo::MemberVarEntry const &a,Offset const &b)
00048 { return(a.off==b); }
00049
00050 template<typename I>static inline const ClassInfo::MemberVarEntry &idx(
00051 const ClassInfo::MemberVarEntry *array,I i)
00052 { return(array[i]); }
00053 };
00054
00055
00056 SymRef VMLinker::_SQPush(NamespaceInfo::SymbolEntryE *se,
00057 NamespaceInfo::SymbolEntryB **update_se,LSymbol::SFlag sflag)
00058 {
00059 if(se->symref<0)
00060 {
00061
00062 Assert(0);
00063 Assert(!update_se);
00064 return(se->symref);
00065 }
00066
00067 SymRef symref;
00068 if(sflag==LSymbol::SStart)
00069 { symref=0; }
00070 else
00071 { symref=master_SymRef_cnt; }
00072 LSymbol symb(se,symref,update_se,sflag);
00073
00074
00075 LSymbol known;
00076 int rv=sq.store(symb,0,&known);
00077 if(rv)
00078 {
00079 Assert(known.se);
00080 return(known.symref);
00081 }
00082
00083 Warning("added %s ($%d) to symbol queue",se->CompleteName().str(),
00084 (int)symref);
00085
00086 if(symref==master_SymRef_cnt)
00087 { ++master_SymRef_cnt; }
00088
00089 return(symb.symref);
00090 }
00091
00092 SymRef VMLinker::_SQQuery(NamespaceInfo::SymbolEntryE *se)
00093 {
00094 Assert(se->symref>=0);
00095
00096 LSymbol key(se,0,NULL,LSymbol::SNone);
00097 LSymbol *known=sq.search(key);
00098 if(known)
00099 { return(known->symref); }
00100 else
00101 { return(master_SymRef_cnt++); }
00102 }
00103
00104 void VMLinker::_SQPop()
00105 {
00106
00107
00108 sq.RemoveSmallest(NULL);
00109 }
00110
00111 bool VMLinker::_SQPeek(LSymbol &ls)
00112 {
00113 LSymbol *s=sq.GetSmallest();
00114 if(s) ls=*s;
00115 return(s);
00116 }
00117
00118
00119 VMLinker::FileNode *VMLinker::_GetDefinitionFile(NamespaceInfo *from_here)
00120 {
00121 FileNode *fn=NULL;
00122
00123
00124
00125
00126
00127
00128 NamespaceInfo *walker=from_here;
00129 for(; walker->parent; walker=walker->parent);
00130
00131 for(FileNode *fni=flist.first(); fni; fni=fni->next)
00132 {
00133 if(fni->f->nspc_root==walker)
00134 { fn=fni; break; }
00135 }
00136
00137
00138
00139 Assert(fn);
00140
00141 return(fn);
00142 }
00143
00144
00145 NamespaceInfo *VMLinker::_MergeNamespaceInfo_Recursive(
00146 NamespaceInfo **head_list,uint nheads)
00147 {
00148 if(!nheads) return(NULL);
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161 NamespaceInfo *dest=NULL;
00162 if(nheads==1)
00163 {
00164
00165
00166 switch(head_list[0]->nstype)
00167 {
00168 case NamespaceInfo::NSNamespace:
00169 {
00170 NamespaceInfo *s=head_list[0];
00171 dest = new NamespaceInfo(s->name,
00172 NULL);
00173
00174
00175
00176 } break;
00177 case NamespaceInfo::NSClass:
00178 {
00179 ClassInfo *s = static_cast<ClassInfo*>(head_list[0]);
00180 ClassInfo *d = new ClassInfo(s->name,
00181 master_TypeID_cnt++,
00182 NULL);
00183
00184
00185
00186 d->size=s->size;
00187 d->nvirtuals=s->nvirtuals;
00188
00189
00190
00191 d->membvar=s->membvar;
00192 dest=d;
00193 } break;
00194 default: Assert(0);
00195 }
00196 head_list[0]->linked=dest;
00197 }
00198 else
00199 {
00200 NamespaceInfo::NSType dest_type=head_list[0]->nstype;
00201 for(uint i=1 ; i<nheads; i++)
00202 {
00203 if(dest_type==head_list[i]->nstype) continue;
00204 Error(head_list[i]->asm_loc,
00205 "%s \"%s\" redefined as %s",
00206 NamespaceInfo::NSType2String(dest_type),
00207 head_list[0]->CompleteName().str(),
00208 NamespaceInfo::NSType2String(head_list[i]->nstype));
00209 Error(head_list[0]->asm_loc,
00210 " this is the location of the first definition");
00211 ++n_errors;
00212
00213 dest_type=NamespaceInfo::NSNamespace;
00214 break;
00215 }
00216
00217 switch(dest_type)
00218 {
00219 case NamespaceInfo::NSNamespace:
00220 {
00221 dest = new NamespaceInfo(head_list[0]->name,
00222 NULL);
00223
00224
00225
00226
00227
00228
00229
00230
00231 } break;
00232 case NamespaceInfo::NSClass:
00233 {
00234 ClassInfo *d = new ClassInfo(head_list[0]->name,
00235 master_TypeID_cnt++,
00236 NULL);
00237
00238
00239
00240 if(!cfg.abandon_out_maps)
00241 {
00242 ClassInfo _unused_ *known=out->tid2classinfo.AddNode(d);
00243 Assert(!known);
00244 }
00245
00246 dest=d;
00247
00248
00249
00250
00251
00252 NonResizeableArray<ClassInfo::MemberVarEntry,uint32>
00253 *most_members=NULL;
00254 for(uint i=0; i<nheads; i++)
00255 {
00256 Assert(head_list[i]->nstype==NamespaceInfo::NSClass);
00257 ClassInfo *s = static_cast<ClassInfo*>(head_list[i]);
00258
00259 if(!i)
00260 {
00261 d->size=s->size;
00262 d->nvirtuals=s->nvirtuals;
00263 most_members=&s->membvar;
00264 }
00265 else
00266 {
00267 if(most_members->n()<s->membvar.n())
00268 { most_members=&s->membvar; }
00269
00270 const char *what=NULL;
00271
00272 if(d->size!=s->size) what="size";
00273 else if(d->nvirtuals!=s->nvirtuals) what="nvirtuals";
00274
00275 if(what)
00276 {
00277 Error(s->asm_loc,
00278 "mismatch of %s property in %s \"%s\"",
00279 what,
00280 NamespaceInfo::NSType2String(dest_type),
00281 s->CompleteName().str());
00282 Error(head_list[0]->asm_loc,
00283 " this is the location of the first "
00284 "occurance");
00285 ++n_errors;
00286 break;
00287 }
00288 }
00289 }
00290
00291
00292 d->membvar=*most_members;
00293 for(uint i=0; i<nheads; i++)
00294 {
00295 Assert(head_list[i]->nstype==NamespaceInfo::NSClass);
00296 ClassInfo *s = static_cast<ClassInfo*>(head_list[i]);
00297
00298
00299
00300 if(&s->membvar==most_members) continue;
00301
00302
00303
00304
00305
00306
00307 bool guess_first = d->membvar.n()==s->membvar.n();
00308
00309
00310
00311 uint n_mismatches=0;
00312 uint n_missing=0;
00313 for(uint j=0,jend=s->membvar.n(); j<jend; j++)
00314 {
00315 ClassInfo::MemberVarEntry *se=&s->membvar[j];
00316 ClassInfo::MemberVarEntry *de=NULL;
00317 if(guess_first && se->off==d->membvar[j].off)
00318 { de=&d->membvar[j]; }
00319 else
00320 {
00321 ssize_t idx=TLBinarySearch(
00322 d->membvar.ptr(),d->membvar.n(),
00323 se->off,MemberVarEntryOffsetOperators());
00324 if(idx>=0) de=&d->membvar[idx];
00325 }
00326
00327 if(!de)
00328 {
00329
00330 ++n_missing;
00331
00332
00333 if(se->vtype.IsPointerType() ||
00334 !cfg.ignore_simple_type_missing)
00335 { ++n_mismatches; }
00336 continue;
00337 }
00338 if(de->vtype!=se->vtype) ++n_mismatches;
00339 if(se->name)
00340 {
00341 if(!de->name) de->name=se->name;
00342 else if(de->name!=se->name) ++n_mismatches;
00343 }
00344 }
00345
00346
00347
00348
00349
00350 if(s->membvar.n()-n_missing!=d->membvar.n())
00351 for(uint j=0,jend=d->membvar.n(); j<jend; j++)
00352 {
00355
00356 ClassInfo::MemberVarEntry *se=NULL;
00357 ClassInfo::MemberVarEntry *de=&d->membvar[j];
00358 if(guess_first && de->off==s->membvar[j].off)
00359 { se=&s->membvar[j]; }
00360 else
00361 {
00362 ssize_t idx=TLBinarySearch(
00363 s->membvar.ptr(),s->membvar.n(),
00364 de->off,MemberVarEntryOffsetOperators());
00365 if(idx>=0) se=&s->membvar[idx];
00366 }
00367
00368
00369
00370
00371 if(se) continue;
00372
00373
00374 if(de->vtype.IsPointerType() ||
00375 !cfg.ignore_simple_type_missing)
00376 { ++n_mismatches; }
00377 else
00378 {
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390 CritAssert(!"not yet implemented");
00391 }
00392 }
00393
00394 if(n_mismatches)
00395 {
00396 Error(s->asm_loc,
00397 "while merging member var info in %s \"%s\": "
00398 "%u mismatches",
00399 NamespaceInfo::NSType2String(dest_type),
00400 s->CompleteName().str(),
00401 n_mismatches);
00402 ++n_errors;
00403 break;
00404 }
00405 }
00406 } break;
00407 default: Assert(0);
00408 }
00409
00410 for(uint i=0; i<nheads; i++)
00411 { head_list[i]->linked=dest; }
00412 }
00413 Assert(dest);
00414
00415
00416 uint nchld=0;
00417 for(uint i=0; i<nheads; i++)
00418 { nchld+=head_list[i]->down.count(); }
00419 if(nchld)
00420 {
00423 NamespaceInfo **chld_list=ALLOC<NamespaceInfo*>(nchld);
00424 nchld=0;
00425 for(uint i=0; i<nheads; i++)
00426 for(NamespaceInfo *j=head_list[i]->down.first(); j; j=j->next)
00427 chld_list[nchld++]=j;
00428
00429
00430
00431
00432
00433 if(nchld<=16)
00434 {
00435 InsertionSort<NamespaceInfo*,
00436 const NamespaceInfo::PtrListOperators<NamespaceInfo> >(
00437 chld_list,nchld,
00438 NamespaceInfo::PtrListOperators<NamespaceInfo>());
00439 }
00440 else
00441 {
00442 HeapSort<NamespaceInfo*,
00443 const NamespaceInfo::PtrListOperators<NamespaceInfo> >(
00444 chld_list,nchld,
00445 NamespaceInfo::PtrListOperators<NamespaceInfo>());
00446 }
00447
00448
00449
00450
00451
00452
00453 TLString name=chld_list[0]->name;
00454 for(uint i0=0,i=1;;i++)
00455 {
00456 if(i<nchld && name==chld_list[i]->name) continue;
00457
00458
00459
00460
00461 NamespaceInfo *c=_MergeNamespaceInfo_Recursive(
00462 chld_list+i0,i-i0);
00463 dest->AddChild(c);
00464
00465 if(i>=nchld) break;
00466 name=chld_list[i]->name;
00467 i0=i;
00468 }
00469
00470 FREE(chld_list);
00471 }
00472
00473
00474
00475 return(dest);
00476 }
00477
00478
00479 void VMLinker::_CheckNamespaceInfo_Recursive(FileNode *fn,NamespaceInfo *ni)
00480 {
00481 do {
00482
00483
00484 Assert(ni->linked);
00485 if(!ni->linked) break;
00486
00487 NamespaceInfo *master=ni->linked;
00488 Assert(ni->nstype==master->nstype);
00489
00490
00491 switch(master->nstype)
00492 {
00493 case NamespaceInfo::NSClass:
00494 {
00495 ClassInfo *cmaster = static_cast<ClassInfo*>(master);
00496 ClassInfo *cni = static_cast<ClassInfo*>(ni);
00497
00498
00499 if(!cmaster->link_info_set)
00500 {
00501
00502 cmaster->base.alloc(cni->base.n());
00503 for(uint32 i=0,iend=cni->base.n(); i<iend; i++)
00504 {
00505 ClassInfo::BaseEntry *d=&cmaster->base[i];
00506 ClassInfo::BaseEntry *s=&cni->base[i];
00507 d->off=s->off;
00508
00509
00510
00511 Assert(s->ci);
00512
00513 ClassInfo *sci=s->ci->ci();
00514 if(sci)
00515 {
00516
00517 d->ci=static_cast<ClassInfo*>(sci->linked);
00518
00519
00520
00521 Assert(d->ci);
00522 Assert(d->ci->ci());
00523 Assert(d->ci->ci()->nstype=NamespaceInfo::NSClass);
00524 }
00525 else
00526 {
00527
00528
00529 d->ci=out->internal_classes.LookupStore(
00530 s->ci->class_tid);
00531 }
00532 }
00533
00534
00535 cmaster->vtable.alloc(cni->vtable.n());
00536 for(uint32 i=0,iend=cni->vtable.n(); i<iend; i++)
00537 {
00538 ClassInfo::VTableEntry *d=&cmaster->vtable[i];
00539 ClassInfo::VTableEntry *s=&cni->vtable[i];
00540
00541
00542 Assert(s->se);
00543
00544
00545
00546
00547 d->se=s->se;
00548 Assert(!d->se->ep() || d->se->ep()->nspc->linked);
00549 }
00550
00551
00552
00553 }
00554 else
00555 {
00556
00557 uint n_mismatches=0;
00558 if(cni->base.n()!=cmaster->base.n())
00559 { ++n_mismatches; }
00560 else for(uint32 i=0,iend=cmaster->base.n(); i<iend; i++)
00561 {
00562 ClassInfo::BaseEntry *d=&cmaster->base[i];
00563 ClassInfo::BaseEntry *s=&cni->base[i];
00564
00565
00566 if(d->off!=s->off) ++n_mismatches;
00567
00568
00569 Assert(s->ci);
00570 ClassInfo *ssci=s->ci->ci();
00571 ClassInfo *dsci=d->ci->ci();
00572 if(ssci && dsci)
00573 {
00574
00575 ClassInfo *sci_lnk=static_cast<ClassInfo*>(
00576 ssci->linked);
00577
00578 Assert(sci_lnk);
00579 Assert(sci_lnk->nstype=NamespaceInfo::NSClass);
00580
00581 if(sci_lnk!=dsci) ++n_mismatches;
00582 }
00583 else if(!ssci && !dsci)
00584 {
00585
00586 if(s->ci->class_tid!=d->ci->class_tid)
00587 { ++n_mismatches; }
00588 }
00589 else
00590 { ++n_mismatches; }
00591 }
00592 if(n_mismatches)
00593 {
00594 Error(cni->asm_loc,
00595 "while merging base class info in %s \"%s\": "
00596 "%u mismatches",
00597 NamespaceInfo::NSType2String(master->nstype),
00598 master->CompleteName().str(),
00599 n_mismatches);
00600 ++n_errors;
00601 }
00602
00603
00604 n_mismatches=0;
00605 if(cni->vtable.n()!=cmaster->vtable.n())
00606 { ++n_mismatches; }
00607 else for(uint32 i=0,iend=cmaster->vtable.n(); i<iend; i++)
00608 {
00609
00610
00611 ClassInfo::VTableEntry *du=&cmaster->vtable[i];
00612 ClassInfo::VTableEntry *su=&cni->vtable[i];
00613
00614
00615
00616 if(!du->se->CompareTo(*su->se)) ++n_mismatches;
00617
00618
00619 if(du->se->ep())
00620 {
00621 NamespaceInfo::SymbolEntryE *d=du->se->ep();
00622 NamespaceInfo::SymbolEntryE *s=su->se->ep();
00623
00624 Assert(s->nspc->linked);
00625 if(d->nspc->linked!=s->nspc->linked)
00626 { ++n_mismatches; }
00627 }
00628 }
00629 if(n_mismatches)
00630 {
00631 Error(cni->asm_loc,
00632 "while merging vtable class info in %s \"%s\": "
00633 "%u mismatches",
00634 NamespaceInfo::NSType2String(master->nstype),
00635 master->CompleteName().str(),
00636 n_mismatches);
00637 ++n_errors;
00638 }
00639 }
00640 }
00641 case NamespaceInfo::NSNamespace:
00642
00643 break;
00644 default: Assert(0);
00645 }
00646
00647 master->link_info_set=1;
00648 } while(0);
00649
00650
00651 for(NamespaceInfo *j=ni->down.first(); j; j=j->next)
00652 _CheckNamespaceInfo_Recursive(fn,j);
00653 }
00654
00655
00656 int VMLinker::_CheckBaseRecursion(ClassInfo *cni)
00657 {
00658 Assert(cni->nstype==NamespaceInfo::NSClass);
00659
00660 int errcnt=0;
00661
00662
00663 if(cni->recursion_flag)
00664 { ++errcnt; return(errcnt); }
00665
00666 cni->recursion_flag=1;
00667 for(uint32 i=0,iend=cni->base.n(); i<iend; i++)
00668 {
00669 ClassInfoIE *cii=cni->base[i].ci;
00670 Assert(cii);
00671 ClassInfo *ci=cii->ci();
00672 if(!ci) continue;
00673 errcnt+=_CheckBaseRecursion(ci);
00674 }
00675 cni->recursion_flag=0;
00676
00677 return(errcnt);
00678 }
00679
00680
00681 void VMLinker::_CheckBaseRecursion_Recursive(FileNode *fn,NamespaceInfo *ni)
00682 {
00683 if(ni->nstype==NamespaceInfo::NSClass &&
00684 _CheckBaseRecursion(static_cast<ClassInfo*>(ni)))
00685 {
00686 Error(ni->asm_loc,
00687 "recursion in base class hierarchy of \"%s\""
00688 " (what'chew doin' to me, Willis?!)",
00689 ni->CompleteName().str());
00690 ++n_errors;
00691 }
00692
00693
00694 for(NamespaceInfo *j=ni->down.first(); j; j=j->next)
00695 _CheckBaseRecursion_Recursive(fn,j);
00696 }
00697
00698
00699 void VMLinker::_MergeNamespaceAndVTableInfo()
00700 {
00701 Assert(!out->nspc_root);
00702
00703
00704 uint nheads=0;
00705 for(FileNode *fn=flist.first(); fn; fn=fn->next)
00706 {
00707 NamespaceInfo *f_nspc_root=fn->f->nspc_root;
00708 if(!f_nspc_root) continue;
00709 ++nheads;
00710 }
00711
00712 if(nheads)
00713 {
00714 NamespaceInfo **head_list=ALLOC<NamespaceInfo*>(nheads);
00715
00716 nheads=0;
00717 for(FileNode *fn=flist.first(); fn; fn=fn->next)
00718 {
00719 NamespaceInfo *f_nspc_root=fn->f->nspc_root;
00720 if(!f_nspc_root) continue;
00721 head_list[nheads++]=f_nspc_root;
00722 }
00723
00724 out->nspc_root=_MergeNamespaceInfo_Recursive(head_list,nheads);
00725
00726 FREE(head_list);
00727 }
00728
00729
00730
00731 if(n_errors) return;
00732
00733
00734
00735
00736
00737 for(FileNode *fn=flist.first(); fn; fn=fn->next)
00738 {
00739 NamespaceInfo *f_nspc_root=fn->f->nspc_root;
00740 if(!f_nspc_root) continue;
00741 _CheckNamespaceInfo_Recursive(fn,f_nspc_root);
00742 }
00743
00744
00745 if(n_errors) return;
00746
00747
00748
00749
00750
00751 for(FileNode *fn=flist.first(); fn; fn=fn->next)
00752 {
00753 NamespaceInfo *f_nspc_root=fn->f->nspc_root;
00754 if(!f_nspc_root) continue;
00755 _CheckBaseRecursion_Recursive(fn,f_nspc_root);
00756 }
00757 }
00758
00759
00760 void VMLinker::_GenerateSymbolProvideMap_AddGlobal(FileNode *fn,
00761 AssemblerFile::_GlobVars *gvar)
00762 {
00763 for(AssemblerFile::GlobalVarList::Iterator i(gvar->globvarq); i; i++)
00764 {
00765 NamespaceInfo::SymbolEntryE *se=(*i)->se;
00766 NamespaceInfo::SymbolEntryE *known=symbol_provide_map.AddNode(se);
00767 if(known)
00768 {
00769 Error(fn->f->filename,
00770 "duplicate variable symbol \"%s\"",se->CompleteName().str());
00771 if(known->nspc)
00772 { Error(known->nspc->asm_loc," this is the location of the "
00773 "previous occurance"); }
00774 ++n_errors;
00775
00776
00777
00778 }
00779
00780 Warning(fn->f->filename,"%s added to provide map",
00781 se->CompleteName().str());
00782 }
00783 }
00784
00785
00786 void VMLinker::_GenerateSymbolProvideMap()
00787 {
00788 symbol_provide_map.clear();
00789
00790 for(FileNode *fn=flist.first(); fn; fn=fn->next)
00791 {
00792 NamespaceInfo *f_nspc_root=fn->f->nspc_root;
00793 if(!f_nspc_root) continue;
00794
00795 for(ProgramStorage::Function *i=fn->f->program.FirstFunction();
00796 i; i=i->next)
00797 {
00798 NamespaceInfo::SymbolEntryE *known=
00799 symbol_provide_map.AddNode(i->se);
00800 if(known)
00801 {
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820 Error(i->loc,
00821 "duplicate function symbol \"%s\"",
00822 i->se->CompleteName().str());
00823 if(known->nspc)
00824 { Error(known->nspc->asm_loc," this is the location "
00825 "of the previous occurance"); }
00826 ++n_errors;
00827
00828 if(known->extid==NamespaceInfo::SymbolEntryE::ExtFunction &&
00829 i->se->extid==NamespaceInfo::SymbolEntryE::ExtFunction &&
00830 (!known->ftype.exported || !i->se->ftype.exported))
00831 { Assert(0); }
00832 }
00833
00834 Warning(i->loc,"%s added to provide map",
00835 i->se->CompleteName().str());
00836 }
00837
00838 _GenerateSymbolProvideMap_AddGlobal(fn,&fn->f->gvar_v);
00839 _GenerateSymbolProvideMap_AddGlobal(fn,&fn->f->gvar_p);
00840 }
00841 }
00842
00843
00844 void VMLinker::_LinkGlobalStorage(FileNode *fn,AssemblerFile::_GlobVars *gvar,
00845 AssemblerFile::_GlobVars *dest,char which)
00846 {
00847 Warning(fn->f->filename,"linking %cglobal storage (%u bytes)",
00848 which,(uint)gvar->size);
00849
00850
00851 Offset base=dest->size;
00852 dest->size+=gvar->size;
00853
00854 for(AssemblerFile::GlobalVarList::Iterator i(gvar->globvarq); i; i++)
00855 {
00856 AssemblerFile::GlobalVarEntry *s=(*i);
00857
00858 dest->globvarq.PushHead(*s);
00859 AssemblerFile::GlobalVarEntry *dest_ent=dest->globvarq.head();
00860
00861 dest_ent->off+=base;
00862
00863 dest_ent->se=NULL;
00864
00865
00866
00867 Assert(!s->se->linked);
00868
00869 Assert(s->se->symref>=0);
00870
00871 Assert(fn->f->symref2globvar.lookup(s->se->symref));
00872
00873
00874 NamespaceInfo *master_parent=s->se->nspc->linked;
00875 Assert(master_parent);
00876 Assert(!master_parent->linked);
00877
00878 master_parent->symbol.PushHead(*s->se);
00879 NamespaceInfo::SymbolEntryE *master_se=master_parent->symbol.head();
00880 master_se->nspc=master_parent;
00881 master_se->symref=_SQQuery(s->se);
00882 master_se->linked=NULL;
00883
00884
00885 s->se->linked=master_se;
00886
00887 dest_ent->se=master_se;
00888
00889
00890 NamespaceInfo::SymbolEntryE *known=NULL;
00891 Assert(master_se->symref>=0);
00892 int srv=master_parent->map_name2symbol.store(master_se,
00893 0,&known);
00894 if(srv)
00895 {
00896 Assert(known);
00897 Assert(!known->linked);
00898 Error(fn->f->filename,
00899 "global variable symbol \"%s\" defined multiple times",
00900 master_se->CompleteName().str());
00901 ++n_errors;
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913 }
00914
00915 if(!cfg.abandon_out_maps)
00916 {
00917 NamespaceInfo::SymbolEntryE _unused_ *known=
00918 out->symref2symbol.AddNode(master_se);
00919 Assert(!known);
00920
00921 bool is_known;
00922 out->symref2globvar.AddNode(dest_ent->se->symref,dest_ent,&is_known);
00923 Assert(!is_known);
00924 }
00925 }
00926 }
00927
00928
00929 void VMLinker::_LinkerFileNeeded(FileNode *fn)
00930 {
00931
00932 if(fn->needed) return;
00933
00934
00935
00936 fn->needed=1;
00937
00938 if(fn->f->slabel_init.pfunc)
00939 {
00940 _SQPush(&fn->f->slabel_init.se);
00941 }
00942
00943 _LinkGlobalStorage(fn,&fn->f->gvar_v,&out->gvar_v,'v');
00944 _LinkGlobalStorage(fn,&fn->f->gvar_p,&out->gvar_p,'p');
00945 }
00946
00947
00948 void VMLinker::_LinkFunction(FileNode *fn,ProgramStorage::Function *psf,
00949 NamespaceInfo::SymbolEntryE *se_linked)
00950 {
00951 Assert(se_linked);
00952
00953 bool is_start_func=(se_linked==&out->slabel_start.se);
00954
00955 Assert(is_start_func || se_linked->symref>0);
00956
00957 ProgramStorage::Function *dest = new ProgramStorage::Function(
00958 se_linked->symref,psf->loc,psf->length());
00959 dest->se=se_linked;
00960
00961
00962 for(PrgAdr adr=0; adr<psf->length(); )
00963 {
00964 const INST::DescEntry *ide=INST::Desc(psf->InstructionAt(adr));
00965 if(!ide)
00966 {
00967 Error(psf->loc,
00968 "illegal instruction at address 0x%x in \"%s\"",
00969 (uint)adr,psf->se->CompleteName().str());
00970 ++n_errors;
00971 break;
00972 }
00973
00974
00975 char *inst_base_src=&psf->index(adr);
00976 dest->append(inst_base_src,ide->size);
00977 char *inst_base_dest=&dest->index(adr);
00978
00979
00980 if(ide->typeid_off)
00981 {
00982
00983 TypeID val=*(TypeID*)(inst_base_src+ide->typeid_off);
00984
00985
00986 TypeID new_val;
00987 if(val<0)
00988 { new_val=val; }
00989 else
00990 {
00991
00992 ClassInfo *found=fn->f->tid2classinfo.lookup(val);
00993 if(!found)
00994 {
00995 Error(dest->loc,
00996 "undeclared TypeID %d at address 0x%x",
00997 (int)val,(uint)adr);
00998 ++n_errors;
00999 new_val=0;
01000 }
01001 else
01002 {
01003 Assert(found->linked);
01004 Assert(found->linked->nstype==NamespaceInfo::NSClass);
01005
01006 ClassInfo *ci=static_cast<ClassInfo*>(found->linked);
01007
01008 switch(psf->InstructionAt(adr))
01009 {
01010 case INST::ONEW:
01011 if(!ci->need_construct)
01012 { _LinkerNeedClassConstruct(ci); }
01013 break;
01014 case INST::SCAST:
01015 case INST::DCAST:
01016 if(!ci->need_cast)
01017 { ci->need_cast=1; }
01018 break;
01019 default: Assert(0);
01020 }
01021
01022 new_val=ci->class_tid;
01023 Assert(new_val);
01024 }
01025 }
01026
01027
01028 *(TypeID*)(inst_base_dest+ide->typeid_off)=(TypeID)new_val;
01029 }
01030
01031 if(ide->symref_off)
01032 {
01033
01034 SymRef val=*(SymRef*)(inst_base_src+ide->symref_off);
01035
01036
01037 SymRef new_val;
01038 if(val<0)
01039 { new_val=val; }
01040 else
01041 {
01042 NamespaceInfo::SymbolEntryE *found=
01043 fn->f->symref2symbol.lookup(val);
01044 if(!found)
01045 {
01046 Error(dest->loc,
01047 "undeclared SymRef $%d at address 0x%x",
01048 (int)val,(uint)adr);
01049 ++n_errors;
01050 new_val=0;
01051 }
01052 else
01053 {
01054
01055
01056 if(found->linked)
01057 {
01058
01059 new_val=found->linked->symref;
01060 }
01061 else
01062 {
01063
01064
01065 new_val=_SQPush(found);
01066 }
01067
01068 Assert(new_val);
01069 }
01070 }
01071
01072
01073
01074
01075 *(SymRef*)(inst_base_dest+ide->symref_off)=(SymRef)new_val;
01076
01077
01078
01079
01080 }
01081
01082
01083 adr+=ide->size;
01084 }
01085
01086
01087
01088
01089
01090
01091
01092 out->program.AddFunction(dest);
01093 if(is_start_func)
01094 { out->slabel_start.pfunc=dest; }
01095
01096 if(!cfg.abandon_out_maps && !is_start_func)
01097 {
01098 bool is_known;
01099 out->symref2function.AddNode(se_linked->symref,dest,&is_known);
01100 Assert(!is_known);
01101 }
01102 }
01103
01104
01105 void VMLinker::_LinkerNeedClassConstruct(ClassInfo *ci)
01106 {
01107
01108 Assert(!ci->linked);
01109
01110
01111 if(ci->need_construct) return;
01112 ci->need_construct=1;
01113
01114 Warning("processing %u vtable entries of %s",
01115 (uint)ci->vtable.n(),ci->CompleteName().str());
01116
01117
01118
01119
01120
01121 for(uint32 i=0,iend=ci->vtable.n(); i<iend; i++)
01122 {
01123 ClassInfo::VTableEntry *ve=&ci->vtable[i];
01124 Assert(ve->se);
01125
01126 if(ve->se->ep())
01127 {
01128
01129 NamespaceInfo::SymbolEntryE *vese=ve->se->ep();
01130 Assert(vese->nspc->linked);
01131
01132
01133
01134 if(vese->linked)
01135 {
01136
01137 ve->se=vese->linked;
01138 }
01139 else
01140 {
01141
01142 _SQPush(vese,&ve->se);
01143 ve->se=NULL;
01144 }
01145 }
01146 else
01147 {
01148
01149
01150
01151
01152
01153 ve->se=out->internal_symbols.LookupStore(ve->se->symref);
01154
01155 }
01156 }
01157 }
01158
01159
01160 void VMLinker::_DoPropagateUseFlags(ClassInfo *from,ClassInfo *cni)
01161 {
01162
01163
01164
01165 if(from->need_construct || from->need_cast)
01166 {
01167 cni->need_cast=1;
01168 }
01169
01170
01171 for(uint32 i=0,iend=cni->base.n(); i<iend; i++)
01172 {
01173 ClassInfoIE *cii=cni->base[i].ci;
01174 Assert(cii);
01175 ClassInfo *ci=cii->ci();
01176 if(!ci) continue;
01177 _DoPropagateUseFlags(from,ci);
01178 }
01179 }
01180
01181 void VMLinker::_PropagateUseFlags_Recursive(NamespaceInfo *ni)
01182 {
01183 if(ni->nstype==NamespaceInfo::NSClass)
01184 {
01185 ClassInfo *ci=static_cast<ClassInfo*>(ni);
01186
01187 if(ci->need_construct || ci->need_cast)
01188 { _DoPropagateUseFlags(ci,ci); }
01189 }
01190
01191
01192 for(NamespaceInfo *j=ni->down.first(); j; j=j->next)
01193 _PropagateUseFlags_Recursive(j);
01194 }
01195
01196
01197 void VMLinker::_CreateInitFunction()
01198 {
01199
01200
01201 ProgramStorage::Function *inifunc=new ProgramStorage::Function(
01202 0,SCLocation());
01203
01204 int n_added=0;
01205 for(FileNode *fn=flist.first(); fn; fn=fn->next)
01206 {
01207 if(!fn->needed) continue;
01208 if(!fn->f->slabel_init.pfunc) continue;
01209
01210
01211 Assert(fn->f->slabel_init.se.linked);
01212
01213 SymRef symref=fn->f->slabel_init.se.linked->symref;
01214 inifunc->append(INST::CALL,symref);
01215 ++n_added;
01216 }
01217 if(!n_added)
01218 {
01219
01220 DELETE(inifunc);
01221 }
01222 else
01223 {
01224
01225 inifunc->append(INST::RET);
01226
01227
01228 out->program.AddFunction(inifunc);
01229 inifunc->se=&out->slabel_init.se;
01230
01231
01232 out->slabel_init.pfunc=inifunc;
01233 out->slabel_init.se.extid=NamespaceInfo::SymbolEntryE::ExtFunction;
01234 out->slabel_init.se.ftype=FuncType(FuncType::Function,0);
01235 out->slabel_init.se.name=".init";
01236 out->slabel_init.se.nspc=out->nspc_root;
01237 out->slabel_init.se.linked=NULL;
01238 }
01239 }
01240
01241 int VMLinker::LinkAll(AssemblerFile *_out)
01242 {
01243
01244 DELETE(out);
01245 out=_out;
01246 n_errors=0;
01247
01248
01249 symbol_provide_map.clear();
01250 master_TypeID_cnt=1;
01251 master_SymRef_cnt=1;
01252 sq.clear();
01253
01254
01255
01256 for(FileNode *fn=flist.first(); fn; fn=fn->next)
01257 {
01258 NamespaceInfo *f_nspc_root=fn->f->nspc_root;
01259 if(!f_nspc_root) continue;
01260
01261 StringTreeDump dump;
01262 dump.append("------------<"+fn->f->filename.path()+
01263 ">------------\n");
01264 f_nspc_root->DumpTree(dump,0);
01265 dump.write(stdout);
01266 }
01267
01268
01269
01270 FileNode *start_fn=NULL;
01271 FileNode *abi_version_fn=NULL;
01272 for(FileNode *fn=flist.first(); fn; fn=fn->next)
01273 {
01274 fn->needed=0;
01275
01276 if(fn->f->slabel_start.pfunc)
01277 {
01278 if(!start_fn)
01279 { start_fn=fn; }
01280 else
01281 {
01282 Error(fn->f->filename,
01283 "multiple start labels; previous definition in %s",
01284 start_fn->f->filename.path().str());
01285 ++n_errors;
01286 }
01287 }
01288
01289 if(fn->f->abi_version)
01290 {
01291 if(!abi_version_fn)
01292 { abi_version_fn=fn; }
01293 else if(abi_version_fn->f->abi_version!=fn->f->abi_version)
01294 {
01295 Error(fn->f->filename,
01296 "incompatible ABI versions: \"%s\" vs \"%s\" in %s",
01297 fn->f->abi_version.str(),
01298 abi_version_fn->f->abi_version.str(),
01299 abi_version_fn->f->filename.path().str());
01300 ++n_errors;
01301 }
01302 }
01303 else
01304 {
01305 Warning(fn->f->filename,
01306 "ABI version information missing; assuming compatible");
01307 }
01308 }
01309 if(!start_fn)
01310 { Error("no start label present"); ++n_errors; }
01311 if(n_errors)
01312 {
01313 Error("bailing out at stage 0 (find start)");
01314 return(n_errors);
01315 }
01316
01317
01318 out->abi_version=abi_version_fn->f->abi_version;
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333 for(FileNode *fn=flist.first(); fn; fn=fn->next)
01334 {
01335 if(fn->f->ResolveIDsNamespaceLocal())
01336 { ++n_errors; }
01337 }
01338 if(n_errors)
01339 {
01340 Error("bailing out at stage 1 (resolve IDs local)");
01341 return(n_errors);
01342 }
01343
01344
01345
01346 _MergeNamespaceAndVTableInfo();
01347 if(n_errors)
01348 {
01349 Error("bailing out at stage 2 (merge namespaces)");
01350 return(n_errors);
01351 }
01352
01353
01354 _GenerateSymbolProvideMap();
01355
01356 if(n_errors)
01357 {
01358 Error("bailing out at stage 3 (create symbol map)");
01359 return(n_errors);
01360 }
01361
01362
01363
01364
01365
01366
01367
01368
01369 out->slabel_start.pfunc=NULL;
01370 _SQPush(&start_fn->f->slabel_start.se,NULL,LSymbol::SStart);
01371
01372
01373 LSymbol ls;
01374 while(_SQPeek(ls))
01375 {
01376 Warning("Looking up %s...",ls.se->CompleteName().str());
01377
01378
01379 FileNode *definition_fn=NULL;
01380 if(ls.se->linked || ls.se->symref<0)
01381 {
01382
01383
01384
01385 Assert(0);
01386 }
01387 else
01388 {
01389
01390
01391
01392 Assert(ls.se->nspc);
01393 NamespaceInfo *linked=ls.se->nspc->linked;
01394 Assert(linked);
01395
01396 NamespaceInfo::SymbolEntryE *found=NULL;
01397 do {
01398
01399 found=symbol_provide_map.lookup(ls.se);
01400 if(found)
01401 {
01402
01403 definition_fn=_GetDefinitionFile(found->nspc);
01404
01405
01406 if(found->linked)
01407 {
01408
01409
01410 ls.se->linked=found->linked;
01411
01412 break;
01413 }
01414
01415
01416
01417
01418 _LinkerFileNeeded(definition_fn);
01419
01420
01421
01422 if(found->linked)
01423 {
01424
01425
01426 ls.se->linked=found->linked;
01427
01428 break;
01429 }
01430
01431
01432
01433 NamespaceInfo *master_parent=found->nspc->linked;
01434 Assert(master_parent);
01435
01436
01437
01438 if(ls.sflag==LSymbol::SStart)
01439 {
01440 out->slabel_start.se=*found;
01441 found=&out->slabel_start.se;
01442 }
01443 else
01444 {
01445 master_parent->symbol.PushHead(*found);
01446 found=master_parent->symbol.head();
01447 }
01448
01449
01450 found->nspc=master_parent;
01451 found->linked=NULL;
01452 found->symref=ls.symref;
01453
01454
01455 ls.se->linked=found;
01456
01457
01458 Assert(found->symref>=0);
01459 int _unused_ srv=master_parent->map_name2symbol.store(
01460 found,0);
01461
01462
01463 Assert(!srv);
01464
01465 if(!cfg.abandon_out_maps)
01466 {
01467 NamespaceInfo::SymbolEntryE _unused_ *known=
01468 out->symref2symbol.AddNode(found);
01469 Assert(!known);
01470 }
01471 }
01472
01473
01474 } while(0);
01475
01476 if(!found)
01477 {
01478 Error(ls.se->nspc->asm_loc,"undefined symbol \"%s\"",
01479 ls.se->CompleteName().str());
01480 ++n_errors;
01481 }
01482 }
01483
01484
01485
01486 if(ls.update_se)
01487 { *ls.update_se=ls.se->linked; }
01488
01489
01490 _SQPop();
01491
01492 if(!ls.se->linked)
01493 {
01494
01495 continue;
01496 }
01497
01498
01499 Assert(definition_fn);
01500
01501 switch(ls.se->extid)
01502 {
01503 case NamespaceInfo::SymbolEntryE::ExtFunction:
01504 {
01505 Warning(ls.se->nspc->asm_loc,"get code for function %s "
01506 "(symref $%d)",
01507 ls.se->CompleteName().str(),(int)ls.se->symref);
01508 Warning(definition_fn->f->filename," looking in this file");
01509
01510
01511 ProgramStorage::Function *pfunc;
01512 if(ls.se==&definition_fn->f->slabel_init.se)
01513 { pfunc=definition_fn->f->slabel_init.pfunc; }
01514 else if(ls.se==&definition_fn->f->slabel_start.se)
01515 { pfunc=definition_fn->f->slabel_start.pfunc; }
01516 else
01517 { pfunc=definition_fn->f->symref2function.lookup(
01518 ls.se->symref); }
01519
01520
01521 Assert(pfunc);
01522
01523 Assert(ls.se->linked->symref==ls.symref);
01524 _LinkFunction(definition_fn,pfunc,ls.se->linked);
01525 } break;
01526 case NamespaceInfo::SymbolEntryE::ExtVariable:
01527
01528
01529 if(ls.se->symref>=0)
01530 { Assert(ls.se->linked->nspc->map_name2symbol.search(
01531 ls.se->name)); }
01532
01533
01534 break;
01535 default: Assert(0);
01536 }
01537 }
01538
01539 if(n_errors)
01540 {
01541 Error("bailing out at stage 4 (resolve symbols)");
01542 return(n_errors);
01543 }
01544
01545 if(out->nspc_root)
01546 {
01547 _PropagateUseFlags_Recursive(out->nspc_root);
01548
01549 _CreateInitFunction();
01550 }
01551
01552
01553 for(FileNode *fn=flist.first(); fn; fn=fn->next)
01554 {
01555 if(!fn->needed)
01556 { Warning(fn->f->filename,"input file not needed"); }
01557 }
01558
01559
01560 if(out->nspc_root)
01561 {
01562 StringTreeDump dump;
01563 out->nspc_root->DumpTree(dump,1);
01564 dump.write(stdout);
01565 }
01566
01567 return(n_errors);
01568 }
01569
01570
01571 int VMLinker::AddFile(AssemblerFile *afile)
01572 {
01573 if(!afile) return(0);
01574
01575 FileNode *n=new FileNode(afile);
01576 flist.append(n);
01577
01578 return(0);
01579 }
01580
01581
01582 VMLinker::VMLinker() :
01583 cfg(),
01584 flist(),
01585 n_errors(0),
01586 sq(8),
01587 master_TypeID_cnt(1),
01588 master_SymRef_cnt(1),
01589 symbol_provide_map(),
01590 out(NULL)
01591 {
01592
01593 }
01594
01595 VMLinker::~VMLinker()
01596 {
01597
01598 DELETE(out);
01599
01600
01601 while(!flist.IsEmpty())
01602 { delete flist.PopFirst(); }
01603 }
01604
01605
01606
01607 VMLinker::Config::Config()
01608 {
01609 ignore_simple_type_missing=0;
01610 abandon_out_maps=0;
01611 }
01612
01613 }
01614
01615
01616 #if 1
01617
01618 #include <lib/message/manager.h>
01619 #include <lib/message/handler_console.h>
01620 #include <vm/input/tasm/tasm-file.h>
01621
01622
01623 static int _DoParseFile(const char *file,VM::AssemblerFile_Plaintext *asmfile,
01624 uint32 cnt)
01625 {
01626 SError error;
01627
01628 int rv=asmfile->ParseFile(file,error,cnt);
01629 if(rv)
01630 {
01631 if(error)
01632 { Error("parsing %s: %s",file,error.msg().str()); }
01633 else
01634 { Error("%d lexer/parser errors",rv); }
01635 return(1);
01636 }
01637
01638 return(0);
01639 }
01640
01641 int main(int argc,char **arg)
01642 {
01643 MessageManager::init();
01644 MessageHandler_Console cons_hdl(
01645 Message::MTAll,
01646
01647 0);
01648
01649 VM::VMLinker linker;
01650
01651 int fail=0;
01652 for(int i=1; i<argc; i++)
01653 {
01654 VM::AssemblerFile_Plaintext *asmfile =
01655 new VM::AssemblerFile_Plaintext();
01656 int rv=_DoParseFile(arg[i],asmfile,i);
01657 if(rv)
01658 { DELETE(asmfile); ++fail; }
01659 else
01660 { linker.AddFile(asmfile); }
01661 }
01662
01663 if(!fail)
01664 {
01665 VM::AssemblerFile *output=new VM::AssemblerFile_Plaintext();
01666
01667 fail=linker.LinkAll(output);
01668 if(!fail)
01669 {
01670 SError error;
01671 fail=output->WriteFile("linker.out",error);
01672 }
01673 }
01674
01675 MessageManager::cleanup();
01676 return(fail);
01677 }
01678
01679 #endif