Mercurial > lcfOS
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/python/ppci/modules.py Mon Dec 24 13:30:12 2012 +0100 @@ -0,0 +1,193 @@ +import struct +from .errors import Error +from .nodes import * +from .builtin import integer, real, char, boolean, void +import os.path + +""" + File format for compiled modules. + * [11] magic identifier + * [STR] mod name + * [STR] signature, a md5 signature of the module. + * [I32] size of code + * code image + * [I32] entrypoint for initcode + * imported modules + ** [I32] num of imported modules + *** [STR] name of module + *** signature of the module + *** [I32] offset in the process image where the interface symbols must be placed + * public interface + ** [I32] num of interface elements + *** [STR] proc name + *** [I32] offset in code image + *** [type] return type + *** [I32] number of parameters + **** parameter + ***** parameter kind + ***** parameter name + ***** parameter type +""" + +MAGIC = b'LCFOSMODC' + +loadedModules = [] + +def loadModule(modname): + """ returns a Module object specified by a name """ + # Check if the module was already loaded: + for mod in loadedModules: + if mod.name == modname: + return mod + + # Try to load the module from file: + srcfilename = modname + '.mod' + binfilename = modname + '.bin' + sourceExists = os.path.exists(srcfilename) + if os.path.exists(binfilename): + if sourceExists: + compileModule() + else: + return loadModuleFromFile(binfilename) + else: + Error("Cannot load module '{0}'!".format(modname)) + +def loadModuleFromFile(filename): + f = open(filename, 'rb') + magic = f.read(len(MAGIC)) + assert(magic == MAGIC) + + # Helper functions: + def readI32(): + int32, = struct.unpack('<I', f.read(4)) + return int32 + def readSTR(): + length = readI32() + b = f.read(length) + return b.decode(encoding='ascii') + def readType(): + code, = f.read(1) + basetypes = {0x11:integer, 0x12:real, 0x13:char,0x14:boolean, 0x15:void} + if code in list(basetypes.keys()): + return basetypes[code] + elif code == 0x20: + dimension, elementType = readI32(), readType() + return ArrayType(dimension, elementType) + elif code == 0x21: + returntype = readType() + numparams = readI32() + parameters = [] + kinds = {0x1:'value', 0x2:'var', 0x3:'const'} + for i in range(numparams): + byt, = f.read(1) + kind = kinds[byt] + name, typ = readSTR(), readType() + parameters.append(Parameter(kind, name, typ)) + return ProcedureType(parameters, returntype) + else: + Error('Reading of this typ not supported') + + # Begin of actual loading + modname = readSTR() + modsignature = readSTR() + codesize = readI32() + image = f.read(codesize) + initcodeentry = readI32() + # Check which modules this module loads: + numimports = readI32() + imports = [] + for i in range(numimports): + modname = readSTR() + signature = readSTR() + symname = readSTR() + offset = readI32() + impsym = ImportedSymbol(modname, symname) + impsym.signature = signature + impsym.offset = offset + imports.append(impsym) + # Modules exported interface: + numexports = readI32() + exports = [] + for i in range(numexports): + name = readSTR() + imageoffset = readI32() # Offset in image where symbol is located + typ = readType() + export = ExportedSymbol(name, typ) + export.imageoffset = imageoffset + exports.append(export) + f.close() + + # Construct imported module object: + module = Module(modname) + module.signature = modsignature + module.exports = exports # Symbols provided to other modules + module.imports = imports # Symbols of others used by this module. + module.initcodeentry = initcodeentry + module.image = image # The binary blob + global loadedModules + loadedModules.append(module) + return module + +def storeModule(mod, filename): + """ Class to store a module in a file """ + f = open(filename, 'wb') + + def writeI32(int32): + f.write( struct.pack('<I', int32) ) + def writeSTR(s): + writeI32(len(s)) + f.write(bytes(s, encoding='ascii')) + def writeType(typ): + if type(typ) is BaseType: + basetypecode = {'integer': 0x11, 'real': 0x12, 'char': 0x13, 'boolean':0x14, 'void':0x15} + code = basetypecode[typ.name] + f.write( bytes([code])) + elif type(typ) is ArrayType: + f.write(bytes([0x20])) + writeI32(typ.dimension) + writeType(typ.elementType) + elif type(typ) is ProcedureType: + f.write(bytes([0x21])) + writeType(typ.returntype) + writeI32(len(typ.parameters)) + for parameter in typ.parameters: + kinds = {'value': 0x1, 'var': 0x2, 'const': 0x3} + kind = kinds[parameter.kind] + f.write(bytes([kind])) + writeSTR(parameter.name) + writeType(parameter.typ) + else: + Error('Type storage not implemented {0}'.format(typ)) + + # Begin of actual storage function + f.write(MAGIC) + writeSTR(mod.name) + writeSTR(mod.signature) + writeI32(len(mod.image)) + f.write(bytes(mod.image)) + writeI32(mod.initcodeentry) + # modules imported symbols: + writeI32(len(mod.imports)) + for imp in mod.imports: + writeSTR(imp.modname) + writeSTR(imp.signature) + writeSTR(imp.name) + writeI32(imp.offset) + # modules provided interface + writeI32(len(mod.exports)) + # Store exported symbols: + for sym in mod.exports: + writeSTR(sym.name) # proc name + writeI32(sym.imageoffset) # proc entry point + writeType(sym.typ) # Procedure type + f.close() + + storeModuleInCache(mod) + +def storeModuleInCache(newmod): + global loadedModules + for mod in loadedModules: + if newmod.name == mod.name: + return + loadedModules.append(newmod) +