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