00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef _VM_INPUT_LINKER_H_
00018 #define _VM_INPUT_LINKER_H_ 1
00019
00027 #include <vm/vmconfig.h>
00028 #include <vm/input/asmfile.h>
00029 #include <lib/tl/tlbtree.h>
00030
00031
00032 namespace VM
00033 {
00034
00043 class VMLinker
00044 {
00045 public:
00047 struct FileNode : LinkedListBase<FileNode>
00048 {
00049 AssemblerFile *f;
00050 bool needed;
00051
00052 inline FileNode(AssemblerFile *_f) : f(_f),needed(0) {}
00053 inline ~FileNode() { DELETE(f); }
00054 };
00055
00057 struct Config
00058 {
00060 bool ignore_simple_type_missing;
00064 bool abandon_out_maps;
00065
00067 Config();
00068 inline ~Config() {}
00069 };
00070
00073 static inline NamespaceInfo *SPM_ORD(NamespaceInfo::SymbolEntryE *se)
00074 { return(se->nspc->linked); }
00075
00080 template<typename T>struct ProvideMapOP :
00081 TLDefaultOperators_Construct_PDT<T>,
00082 TLDefaultOperators_Allocation
00083 {
00084 static inline int _cmp_name(T const &a,T const &b)
00085 { return(a->name.compare(b->name)); }
00086
00087
00088 static inline bool lt(T const &a,T const &b)
00089 {
00090 int rv=_cmp_name(a,b);
00091 return(rv ? rv<0 : SPM_ORD(a)<SPM_ORD(b));
00092 }
00093 static inline bool le(T const &a,T const &b)
00094 {
00095 int rv=_cmp_name(a,b);
00096 return(rv ? rv<0 : SPM_ORD(a)<=SPM_ORD(b));
00097 }
00098 static inline bool gt(T const &a,T const &b)
00099 { return(lt(b,a)); }
00100 static inline bool ge(T const &a,T const &b)
00101 { return(le(b,a)); }
00102
00103 static inline bool eq(T const &a,T const &b)
00104 { return(SPM_ORD(a)==SPM_ORD(b) && _cmp_name(a,b)==0); }
00105 static inline bool ne(T const &a,T const &b)
00106 { return(SPM_ORD(a)!=SPM_ORD(b) || _cmp_name(a,b)!=0); }
00107 };
00108
00110 struct LSymbol
00111 {
00112 NamespaceInfo::SymbolEntryE *se;
00113 SymRef symref;
00114
00115 NamespaceInfo::SymbolEntryB **update_se;
00116 enum SFlag
00117 {
00118 SNone=0,
00119 SStart,
00120 } sflag;
00121
00122 inline LSymbol() : se(NULL),symref(0),update_se(NULL),
00123 sflag(SNone) {}
00124 inline LSymbol(NamespaceInfo::SymbolEntryE *_se,SymRef _symref,
00125 NamespaceInfo::SymbolEntryB **_update_se,SFlag _sflag) :
00126 se(_se),symref(_symref),update_se(_update_se),sflag(_sflag) {}
00127 inline ~LSymbol() {}
00128
00129
00130
00131
00132
00133 typedef ProvideMapOP<NamespaceInfo::SymbolEntryE*> PMOP;
00134 inline bool operator<(const LSymbol &b) const
00135 { return(PMOP::lt(se,b.se)); }
00136 inline bool operator>(const LSymbol &b) const
00137 { return(PMOP::gt(se,b.se)); }
00138 inline bool operator==(const LSymbol &b) const
00139 { return(PMOP::eq(se,b.se)); }
00140 inline bool operator!=(const LSymbol &b) const
00141 { return(PMOP::ne(se,b.se)); }
00142 };
00143
00145 typedef TLBTree< LSymbol,TLDefaultOperators_CDT<LSymbol> > SymbolQueue;
00146
00156 class SymbolProvideMap
00157 {
00158 private:
00159 TLBTree< NamespaceInfo::SymbolEntryE*,
00160 ProvideMapOP<NamespaceInfo::SymbolEntryE*> > map;
00161
00163 SymbolProvideMap(const SymbolProvideMap &);
00165 void operator=(const SymbolProvideMap &);
00166 public:
00168 inline SymbolProvideMap() : map() {}
00170 inline ~SymbolProvideMap() {}
00171
00177 NamespaceInfo::SymbolEntryE *AddNode(
00178 NamespaceInfo::SymbolEntryE *s);
00179
00191 NamespaceInfo::SymbolEntryE *lookup(
00192 NamespaceInfo::SymbolEntryE *symb)
00193 {
00194 NamespaceInfo::SymbolEntryE **found=map.search(symb);
00195 return(found ? *found : NULL);
00196 }
00197
00199 inline void clear()
00200 { map.clear(); }
00201 };
00202
00203 private:
00205 Config cfg;
00206
00208 LinkedList<FileNode> flist;
00209
00211 int n_errors;
00212
00226 SymbolQueue sq;
00227
00230 TypeID master_TypeID_cnt;
00231
00233 SymRef master_SymRef_cnt;
00234
00237 SymbolProvideMap symbol_provide_map;
00238
00249 AssemblerFile *out;
00250
00257 void _MergeNamespaceAndVTableInfo();
00259 NamespaceInfo *_MergeNamespaceInfo_Recursive(NamespaceInfo **head_list,
00260 uint nheads);
00263 void _CheckNamespaceInfo_Recursive(FileNode *fn,NamespaceInfo *ni);
00264
00273 void _LinkFunction(FileNode *fn,ProgramStorage::Function *psf,
00274 NamespaceInfo::SymbolEntryE *se_linked);
00275
00282 void _LinkGlobalStorage(FileNode *fn,AssemblerFile::_GlobVars *gvar,
00283 AssemblerFile::_GlobVars *dest,char which);
00284
00292 void _LinkerFileNeeded(FileNode *fn);
00293
00300 void _LinkerNeedClassConstruct(ClassInfo *ci);
00301
00312 int _CheckBaseRecursion(ClassInfo *cni);
00313
00315 void _CheckBaseRecursion_Recursive(FileNode *fn,NamespaceInfo *ni);
00316
00318 void _PropagateUseFlags_Recursive(NamespaceInfo *ni);
00320 void _DoPropagateUseFlags(ClassInfo *from,ClassInfo *cni);
00321
00323 void _GenerateSymbolProvideMap();
00325 void _GenerateSymbolProvideMap_AddGlobal(FileNode *fn,
00326 AssemblerFile::_GlobVars *gvar);
00327
00329 void _CreateInitFunction();
00330
00333 FileNode *_GetDefinitionFile(NamespaceInfo *from_here);
00334
00336 SymRef _SQPush(NamespaceInfo::SymbolEntryE *,
00337 NamespaceInfo::SymbolEntryB **update_se=NULL,
00338 LSymbol::SFlag sflag=LSymbol::SNone);
00340 SymRef _SQQuery(NamespaceInfo::SymbolEntryE *ni);
00342 void _SQPop();
00344 bool _SQPeek(LSymbol &ls);
00345
00347 VMLinker(const VMLinker &);
00349 void operator=(const VMLinker &);
00350 public:
00352 VMLinker();
00354 ~VMLinker();
00355
00368 int AddFile(AssemblerFile *afile);
00369
00382 int LinkAll(AssemblerFile *out);
00383 };
00384
00385 }
00386
00387 #endif