Mercurial > lcfOS
comparison python/ppci/modules.py @ 96:a350055d6119
movage
author | windel |
---|---|
date | Mon, 24 Dec 2012 13:30:12 +0100 |
parents | python/libs/compiler/modules.py@32078200cdd6 |
children |
comparison
equal
deleted
inserted
replaced
95:4a37d6992bd3 | 96:a350055d6119 |
---|---|
1 import struct | |
2 from .errors import Error | |
3 from .nodes import * | |
4 from .builtin import integer, real, char, boolean, void | |
5 import os.path | |
6 | |
7 """ | |
8 File format for compiled modules. | |
9 * [11] magic identifier | |
10 * [STR] mod name | |
11 * [STR] signature, a md5 signature of the module. | |
12 * [I32] size of code | |
13 * code image | |
14 * [I32] entrypoint for initcode | |
15 * imported modules | |
16 ** [I32] num of imported modules | |
17 *** [STR] name of module | |
18 *** signature of the module | |
19 *** [I32] offset in the process image where the interface symbols must be placed | |
20 * public interface | |
21 ** [I32] num of interface elements | |
22 *** [STR] proc name | |
23 *** [I32] offset in code image | |
24 *** [type] return type | |
25 *** [I32] number of parameters | |
26 **** parameter | |
27 ***** parameter kind | |
28 ***** parameter name | |
29 ***** parameter type | |
30 """ | |
31 | |
32 MAGIC = b'LCFOSMODC' | |
33 | |
34 loadedModules = [] | |
35 | |
36 def loadModule(modname): | |
37 """ returns a Module object specified by a name """ | |
38 # Check if the module was already loaded: | |
39 for mod in loadedModules: | |
40 if mod.name == modname: | |
41 return mod | |
42 | |
43 # Try to load the module from file: | |
44 srcfilename = modname + '.mod' | |
45 binfilename = modname + '.bin' | |
46 sourceExists = os.path.exists(srcfilename) | |
47 if os.path.exists(binfilename): | |
48 if sourceExists: | |
49 compileModule() | |
50 else: | |
51 return loadModuleFromFile(binfilename) | |
52 else: | |
53 Error("Cannot load module '{0}'!".format(modname)) | |
54 | |
55 def loadModuleFromFile(filename): | |
56 f = open(filename, 'rb') | |
57 magic = f.read(len(MAGIC)) | |
58 assert(magic == MAGIC) | |
59 | |
60 # Helper functions: | |
61 def readI32(): | |
62 int32, = struct.unpack('<I', f.read(4)) | |
63 return int32 | |
64 def readSTR(): | |
65 length = readI32() | |
66 b = f.read(length) | |
67 return b.decode(encoding='ascii') | |
68 def readType(): | |
69 code, = f.read(1) | |
70 basetypes = {0x11:integer, 0x12:real, 0x13:char,0x14:boolean, 0x15:void} | |
71 if code in list(basetypes.keys()): | |
72 return basetypes[code] | |
73 elif code == 0x20: | |
74 dimension, elementType = readI32(), readType() | |
75 return ArrayType(dimension, elementType) | |
76 elif code == 0x21: | |
77 returntype = readType() | |
78 numparams = readI32() | |
79 parameters = [] | |
80 kinds = {0x1:'value', 0x2:'var', 0x3:'const'} | |
81 for i in range(numparams): | |
82 byt, = f.read(1) | |
83 kind = kinds[byt] | |
84 name, typ = readSTR(), readType() | |
85 parameters.append(Parameter(kind, name, typ)) | |
86 return ProcedureType(parameters, returntype) | |
87 else: | |
88 Error('Reading of this typ not supported') | |
89 | |
90 # Begin of actual loading | |
91 modname = readSTR() | |
92 modsignature = readSTR() | |
93 codesize = readI32() | |
94 image = f.read(codesize) | |
95 initcodeentry = readI32() | |
96 # Check which modules this module loads: | |
97 numimports = readI32() | |
98 imports = [] | |
99 for i in range(numimports): | |
100 modname = readSTR() | |
101 signature = readSTR() | |
102 symname = readSTR() | |
103 offset = readI32() | |
104 impsym = ImportedSymbol(modname, symname) | |
105 impsym.signature = signature | |
106 impsym.offset = offset | |
107 imports.append(impsym) | |
108 # Modules exported interface: | |
109 numexports = readI32() | |
110 exports = [] | |
111 for i in range(numexports): | |
112 name = readSTR() | |
113 imageoffset = readI32() # Offset in image where symbol is located | |
114 typ = readType() | |
115 export = ExportedSymbol(name, typ) | |
116 export.imageoffset = imageoffset | |
117 exports.append(export) | |
118 f.close() | |
119 | |
120 # Construct imported module object: | |
121 module = Module(modname) | |
122 module.signature = modsignature | |
123 module.exports = exports # Symbols provided to other modules | |
124 module.imports = imports # Symbols of others used by this module. | |
125 module.initcodeentry = initcodeentry | |
126 module.image = image # The binary blob | |
127 global loadedModules | |
128 loadedModules.append(module) | |
129 return module | |
130 | |
131 def storeModule(mod, filename): | |
132 """ Class to store a module in a file """ | |
133 f = open(filename, 'wb') | |
134 | |
135 def writeI32(int32): | |
136 f.write( struct.pack('<I', int32) ) | |
137 def writeSTR(s): | |
138 writeI32(len(s)) | |
139 f.write(bytes(s, encoding='ascii')) | |
140 def writeType(typ): | |
141 if type(typ) is BaseType: | |
142 basetypecode = {'integer': 0x11, 'real': 0x12, 'char': 0x13, 'boolean':0x14, 'void':0x15} | |
143 code = basetypecode[typ.name] | |
144 f.write( bytes([code])) | |
145 elif type(typ) is ArrayType: | |
146 f.write(bytes([0x20])) | |
147 writeI32(typ.dimension) | |
148 writeType(typ.elementType) | |
149 elif type(typ) is ProcedureType: | |
150 f.write(bytes([0x21])) | |
151 writeType(typ.returntype) | |
152 writeI32(len(typ.parameters)) | |
153 for parameter in typ.parameters: | |
154 kinds = {'value': 0x1, 'var': 0x2, 'const': 0x3} | |
155 kind = kinds[parameter.kind] | |
156 f.write(bytes([kind])) | |
157 writeSTR(parameter.name) | |
158 writeType(parameter.typ) | |
159 else: | |
160 Error('Type storage not implemented {0}'.format(typ)) | |
161 | |
162 # Begin of actual storage function | |
163 f.write(MAGIC) | |
164 writeSTR(mod.name) | |
165 writeSTR(mod.signature) | |
166 writeI32(len(mod.image)) | |
167 f.write(bytes(mod.image)) | |
168 writeI32(mod.initcodeentry) | |
169 # modules imported symbols: | |
170 writeI32(len(mod.imports)) | |
171 for imp in mod.imports: | |
172 writeSTR(imp.modname) | |
173 writeSTR(imp.signature) | |
174 writeSTR(imp.name) | |
175 writeI32(imp.offset) | |
176 # modules provided interface | |
177 writeI32(len(mod.exports)) | |
178 # Store exported symbols: | |
179 for sym in mod.exports: | |
180 writeSTR(sym.name) # proc name | |
181 writeI32(sym.imageoffset) # proc entry point | |
182 writeType(sym.typ) # Procedure type | |
183 f.close() | |
184 | |
185 storeModuleInCache(mod) | |
186 | |
187 def storeModuleInCache(newmod): | |
188 global loadedModules | |
189 for mod in loadedModules: | |
190 if newmod.name == mod.name: | |
191 return | |
192 loadedModules.append(newmod) | |
193 |