Changeset 59
- Timestamp:
- 12/01/05 23:22:51 (3 years ago)
- Files:
-
- trunk/buildtest.bat (added)
- trunk/buildutils.bat (added)
- trunk/ddl/DynamicLibrary.d (modified) (1 diff)
- trunk/ddl/DynamicModule.d (modified) (1 diff)
- trunk/ddl/Linker.d (modified) (1 diff)
- trunk/ddl/Mangle.d (added)
- trunk/ddl/insitu/InSituModule.d (modified) (1 diff)
- trunk/ddl/omf/OMFModule.d (modified) (1 diff)
- trunk/ddltest.d (deleted)
- trunk/test.d (deleted)
- trunk/test/linktest1.d (added)
- trunk/test/linktest2.d (added)
- trunk/test/mangle.test1.d (added)
- trunk/test/testc.d (added)
- trunk/testc.d (deleted)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/ddl/DynamicLibrary.d
r16 r59 27 27 private import ddl.ExportSymbol; 28 28 private import ddl.DynamicModule; 29 private import ddl.Mangle; 29 30 30 interfaceDynamicLibrary{31 abstract class DynamicLibrary{ 31 32 public ExportSymbol[] getExports(); 32 33 public ExportSymbol getExport(char[] name); 33 34 public DynamicModule[] getModules(); 35 36 public void* getExportAddress(char[] name){ 37 return this.getExport(name).address; 38 } 39 40 template getField(T, char[] name) 41 { 42 T getField() { return cast(T)getExportAddress("_D" ~ mangleText!(name) ~ mangleType!(T)); } 43 } 44 45 template getFunction(RetT, char [] name) 46 { 47 RetT function() getFunction() { return cast(RetT function() )getExportAddress("_D" ~ mangleText!(name) ~ "F" ~ "Z" ~ mangleType!(RetT)); } 48 } 49 50 template getFunction(RetT, char [] name, P1) 51 { 52 RetT function(P1) getFunction() { return cast(RetT function(P1))getExportAddress("_D" ~ mangleText!(name) ~ "F" ~ mangleType!(P1) ~ "Z" ~ mangleType!(RetT)); 53 } 54 } 55 56 template getFunction(RetT, char [] name, P1, P2) 57 { 58 RetT function(P1, P2) getFunction() { return cast(RetT function(P1, P2))getExportAddress("_D" ~ 59 mangleText!(name) ~ "F" ~ mangleType!(P1) ~ mangleType!(P2) ~ "Z" ~ mangleType!(RetT)); 60 } 61 } 34 62 } trunk/ddl/DynamicModule.d
r18 r59 25 25 module ddl.DynamicModule; 26 26 27 /** 28 Authors: Eric Anderton 29 License: BSD Derivative (see source for details) 30 Copyright: 2005 Eric Anderton 31 */ 32 //TODO: change so that a module yields what modules namespaces it depends on, if possible. 33 27 34 private import ddl.ExportSymbol; 28 35 29 interface DynamicModule{ 36 /** 37 Represents a binary module within DDL. 38 39 Once a module is loaded, it is techncially not usable until all of its internal fixups 40 and external dependencies are resolved. Resolution is performed via the resolveDependency and 41 resolveDependencies methods. 42 */ 43 //TODO: add a way to delay the actual resolution to a separate call, as to optimize the linker 44 abstract class DynamicModule{ 45 46 /** 47 Returns the name of the module. 48 49 While the result of getName() is largely compiler dependent for .asm or .c 50 based binary files, D compilers reliably use the file name with the '.d' file extension 51 for the name of the module. 52 53 Returns: the module's name 54 */ 30 55 public char[] getName(); 56 57 /** 58 The behavior of getDependencies is somewhat obtuse: it will return only what dependencies 59 it presently needs in order to be resolved. Should the module be completely resolved, 60 getDependencies will return null; 61 62 Returns: an array of symbols the module depends upon. 63 64 See_Also: 65 isResolved 66 */ 31 67 public char[][] getDependencies(); 68 69 /** 70 Attempts to resolve a single dependency that the module may have. 71 72 Should the dependency not exist, no effect takes place. This lazy behavior is done to help 73 ease runtine linking by reducing the number of checks and exceptions involved in the process. 74 75 Determining the sucess of resolving all of the module's dependencies is determined via isResolved. 76 77 Params: 78 x = the name of the symbol to resolve 79 address = the address of the external symbol 80 */ 32 81 public void resolveDependency(char[] name,void* address); 82 83 /** 84 Attempts to resolve a single dependency that the module may have. 85 86 Should the dependency not exist, no effect takes place. This lazy behavior is done to help 87 ease runtine linking by reducing the number of checks and exceptions involved in the process. 88 89 Determining the sucess of resolving all of the module's dependencies is determined via isResolved. 90 91 Params: 92 sym = an export to mate with a dependency in this module 93 */ 94 public void resolveDependency(ExportSymbol sym){ 95 this.resolveDependency(sym.name,sym.address); 96 } 97 98 /** 99 Resolves a set of dependencies that the module may have. 100 101 Similar to resolveDependency, this method attempts to resolve a series of symbols provided 102 in the array 'exports'. This is provided to allow for symmetry between modules so that 103 resolving dependencies on a module-by-module basis is simple to perform. 104 105 Examples: 106 --- 107 DynamicModule a,b; 108 a.resolveDependencies(b.getExports); // attempt to satisfy a's dependencies via b's exports 109 --- 110 111 Params: 112 exports = an array of exports as provided from an external source, such as another DynamicModule 113 See_Also: 114 getExports 115 */ 33 116 public void resolveDependencies(ExportSymbol[] exports); 117 118 /** 119 Returns the set of all exports for the module. 120 */ 34 121 public ExportSymbol[] getExports(); 122 123 /** 124 Gets a specific export by name. If the export does not exist, the method returns ExportSymbol.init. 125 */ 35 126 public ExportSymbol getExport(char[] name); 36 public bit isResolved(); // do we have any exports left to resolve? 127 128 /** 129 Returns the current resolution state of the module. 130 131 Generally speaking, isResolved is false if there are still external symbols (dependencies to 132 resolve. If all these dependencies are resolved, then isResolved returns true. 133 134 It is ill-advised to attempt to use any symbols returned from a DynamicModule in an interactive 135 way (binding to functions and so-forth) if the module is not completely resolved. To do otherwise 136 is undefined and could easily result in a protection-fault/segmentation-fault. 137 */ 138 public bit isResolved(); 139 140 /** 141 Determines if the module is being linked. 142 143 This field determines the current link state of the module. 144 It is used exclusively during link procedures as a stop-gap against revisiting the same module 145 during a full link. 146 147 If true, the module is being linked. If false, the module is not being linked. 148 */ 149 public bit isLinking; 37 150 } 38 151 trunk/ddl/Linker.d
r18 r59 25 25 module ddl.Linker; 26 26 27 private import ddl.CachedLoader; 27 /** 28 Authors: Eric Anderton 29 License: BSD Derivative (see source for details) 30 Copyright: 2005 Eric Anderton 31 */ 32 33 //private import ddl.CachedLoader; 28 34 private import ddl.ExportSymbol; 29 35 private import ddl.DynamicLibrary; 30 36 private import ddl.DynamicModule; 31 37 private import ddl.LibrarySearchPath; 32 private import ddl.LibraryValidator; 33 34 class Linker : CachedLoader{ 38 //private import ddl.LibraryValidator; 39 private import ddl.Demangle; 40 41 private import std.stdio; 42 private import std.moduleinit; // used for ModuleInfo 43 44 /** 45 Exception class used exclusively by the Linker. 46 47 LinkExceptions are generated when the linker cannot resolve a module during the linking process. 48 */ 49 class LinkException : Exception{ 50 DynamicModule mod; 51 52 /** 53 Module that prompted the link exception. 54 */ 55 DynamicModule reason(){ 56 return this.mod; 57 } 58 59 /** 60 Default constructor. 61 62 Params: 63 reason = the module that prompts the exception 64 */ 65 public this(DynamicModule reason){ 66 super("LinkException: '" ~ reason.getName ~ "'"); 67 this.mod = reason; 68 } 69 } 70 71 72 /** 73 General-Purpose runtime linker for DDL. 74 */ 75 class Linker{ 76 /** 77 Library list for libraries used for linking. 78 79 The order of insertion into the library list is used as a priority scheme 80 when attempting to link new modules into the runtime. The first library 81 added to the linker should be the current in-situ library, should linking 82 to classes and types in the current runtime be a requirement. In any case 83 the next candidates for addition to the linker should be the runtime libraries 84 in no particular order. 85 86 The linker will attept to link against the first library first, and so on 87 down the list. 88 */ 89 public DynamicLibrary[] libraries; 90 91 /** 92 Default constructor. 93 */ 35 94 public this(){ 36 super(); 37 } 38 39 public this(LibrarySearchPath searchPath){ 40 super(searchPath); 41 } 42 43 public this(LibrarySearchPath searchPath,LibraryValidator validator){ 44 super(searchPath,validator); 45 } 46 47 /** Overrides default behavior of just pulling in the library from the parent. 48 The library is loaded and its publics are serviced to all the other libs. 49 Then, the dependencies are gathered from the cache and fixed up. 50 Finally the library is returned. 51 52 TODO: this is patently non-threadsafe. 53 TODO: enhance this with namespace-based scoping and searching 54 */ 55 protected DynamicLibrary loadNewLibrary(char[] filename){ 56 DynamicLibrary newLib = super.loadNewLibrary(filename); 57 58 foreach(DynamicModule newMod; newLib.getModules()){ 59 foreach(DynamicLibrary oldLib; super.cache){ 60 foreach(DynamicModule oldMod; oldLib.getModules()){ 61 if(!oldMod.isResolved()){ 62 oldMod.resolveDependencies(newMod.getExports()); 63 } 64 if(!newMod.isResolved()){ 65 newMod.resolveDependencies(oldMod.getExports()); 95 // do nothing 96 } 97 98 /** 99 Adds a library to the linker to be used during link operations. 100 101 Modules are included into the internal cross-reference only if they are D modules. 102 */ 103 void add(DynamicLibrary lib){ 104 foreach(DynamicModule mod; lib.getModules){ 105 writefln("add: %s",mod.getName); 106 } 107 libraries ~= lib; 108 } 109 110 /** 111 Initalizes a ModuleInfo instance from a DynamicModule. 112 */ 113 protected void initModule(ModuleInfo m, int skip){ 114 if(!m) return; 115 if (m.flags & MIctordone) return; 116 117 debug printf("Module: %.*s %0.8X\n",m.name,m); 118 if (m.ctor || m.dtor) 119 { 120 if (m.flags & MIctorstart) 121 { if (skip) 122 return; 123 throw new ModuleCtorError(m); 124 } 125 m.flags |= MIctorstart; 126 foreach(ModuleInfo imported; m.importedModules){ 127 initModule(imported,0); 128 } 129 if (m.ctor) 130 (*m.ctor)(); 131 m.flags &= ~MIctorstart; 132 m.flags |= MIctordone; 133 134 //TODO: Now that construction is done, register the destructor 135 } 136 else 137 { 138 m.flags |= MIctordone; 139 foreach(ModuleInfo imported; m.importedModules){ 140 initModule(imported,1); 141 } 142 } 143 } 144 145 /** 146 Links a module against the linker's internal cross-reference. 147 148 This implementation performs a long search of modules, then discrete symbols in the 149 cross-reference. 150 */ 151 public void link(DynamicModule mod){ 152 //protect against infinite recursion here by returning early 153 //by this, we count on the module being resolved further up the call stack 154 if(mod.isLinking) return; 155 156 mod.isLinking = true; 157 158 foreach(char[] dep; mod.getDependencies){ 159 ExportSymbol sym = ExportSymbol.init; 160 foreach(DynamicLibrary lib; this.libraries){ 161 foreach(DynamicModule libMod; lib.getModules){ 162 sym = libMod.getExport(dep); 163 if(sym != ExportSymbol.init){ 164 if(!libMod.isResolved()){ 165 this.link(libMod); 166 } 167 mod.resolveDependency(sym); 168 goto nextDep; // why keep looping? get the heck out -- we're done! 66 169 } 67 170 } 68 171 } 69 } 70 71 return newLib; // return the new library so it may be added to the cache by the superclass 172 nextDep: 173 if(sym == ExportSymbol.init){ 174 writefln("cannot find %s",dep); 175 } 176 } 177 //TODO: possible mod.resolveInternals() call here. 178 mod.isLinking = false; 179 180 if(!mod.isResolved()){ 181 throw new LinkException(mod); 182 } 183 184 // dig up the ModuleInfo (if applicable) and initalize it! 185 foreach(ExportSymbol sym; mod.getExports){ 186 if(getSymbolType(sym.name) == SymbolType.ModuleInfo){ 187 // found it, now get it and run the constructor 188 ModuleInfo moduleInfo = cast(ModuleInfo)(sym.address); 189 initModule(moduleInfo,0); 190 } 191 } 192 } 193 194 /** 195 Links a library against the linker's internal cross-reference. 196 197 There is a subtle difference between linking a lib and linking a lib that has been 198 added to the cross-reference. If every module in the lib is merely dependent upon 199 modules that exist in the cross-reference already, then just calling link will do 200 the task. Otherwise, the lib should be added to the cross-reference first, before 201 proceeding with the actual link. 202 203 Exmaples: 204 --- 205 DynamicLibrary lib; 206 Linker linker; 207 208 linker.add(lib); // add to xref first 209 linker.link(lib); // link in the library and its aggregate modules 210 --- 211 */ 212 public void link(DynamicLibrary lib){ 213 foreach(DynamicModule mod; lib.getModules){ 214 this.link(mod); 215 } 72 216 } 73 217 } trunk/ddl/insitu/InSituModule.d
r27 r59 61 61 62 62 public ExportSymbol getExport(char[] name){ 63 return exports[name]; 63 if(name in exports) return exports[name]; 64 else return ExportSymbol.init; 64 65 } 65 66 trunk/ddl/omf/OMFModule.d
r46 r59 79 79 80 80 public ExportSymbol getExport(char[] name){ 81 return exports[name]; 81 if(name in exports) return exports[name]; 82 else return ExportSymbol.init; 82 83 } 83 84
