Mercurial > lcfOS
diff python/ir/bitreader.py @ 147:4e79484a9d47
Moved core to ir folder
author | Windel Bouwman |
---|---|
date | Fri, 22 Feb 2013 10:33:48 +0100 |
parents | python/ppci/core/bitreader.py@6a303f835c6d |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/python/ir/bitreader.py Fri Feb 22 10:33:48 2013 +0100 @@ -0,0 +1,134 @@ +from .errors import CompilerException +from .module import Module +import struct + +def enum(**enums): + return type('Enum', (), enums) + +BitCodes = enum(END_BLOCK=0, ENTER_SUBBLOCK=1) + +class BitstreamReader: + def __init__(self, f): + self.f = f + # Initialize the bitreader: + self.bitsInCurrent = 32 + self.curWord = self.getWord() + self.curCodeSize = 2 + def getWord(self): + bts = self.f.read(4) + return struct.unpack('<I', bts)[0] + def Read(self, numbits): + if numbits > 32: + raise CompilerException("Cannot read more than 32 bits") + if self.bitsInCurrent >= numbits: + # numbits inside the current word: + R = self.curWord & ((1 << numbits) - 1) + self.curWord = self.curWord >> numbits + self.bitsInCurrent -= numbits + return R + R = self.curWord + self.curWord = self.getWord() + bitsLeft = numbits - self.bitsInCurrent + + # Add remaining bits: + R |= (self.curWord & (0xFFFFFFFF >> (32 - bitsLeft))) << self.bitsInCurrent + + # Update curword and bits in current: + self.curWord = self.curWord >> bitsLeft + self.bitsInCurrent = 32 - bitsLeft + return R + def ReadVBR(self, numbits): + """ Read variable bits, checking for the last bit is zero. """ + piece = self.Read(numbits) + if (piece & (1 << (numbits - 1))) == 0: + return piece + result = 0 + nextbit = 0 + while True: + mask = (1 << (numbits - 1)) - 1 + result |= ( piece & mask ) << nextbit + if (piece & (1 << (numbits - 1))) == 0: + return result + nextbit += numbits - 1 + piece = self.Read(numbits) + def ReadCode(self): + """ Read the code depending on the current code size """ + return self.Read(self.curCodeSize) + def ReadSubBlockId(self): + return self.ReadVBR(8) + def EnterSubBlock(self, blockId): + pass + +BLOCKINFO_BLOCKID = 0 +FIRST_APPLICATION_BLOCKID = 8 +MODULE_BLOCKID = FIRST_APPLICATION_BLOCKID + +class BitcodeReader: + def __init__(self, f): + self.stream = BitstreamReader(f) + def parseModule(self): + for bitsig in [ord('B'), ord('C')]: + if self.stream.Read(8) != bitsig: + raise CompilerException('Invalid bitcode signature') + for bitsig in [0x0, 0xC, 0xE, 0xD]: + if self.stream.Read(4) != bitsig: + raise CompilerException('Invalid bitcode signature') + while True: + code = self.stream.ReadCode() + if code != BitCodes.ENTER_SUBBLOCK: + raise CompilerException('Invalid record at toplevel') + blockId = self.stream.ReadSubBlockId() + if blockId == MODULE_BLOCKID: + print('module block') + pass + else: + print('Block id:', blockId) + raise + return Module() + +class BitstreamWriter: + def __init__(self, f): + self.f = f + self.u32 = 0 + self.curpos = 0 + def Emit1(self, val): + self.Emit(val, 1) + def Emit(self, val, numbits): + """ Emits value using numbits bits """ + if numbits == 1: + if val != 0: + self.u32 |= (0x1 << self.curpos) + self.curpos += 1 + if self.curpos == 32: + self.writeWord() + elif numbits > 1: + for i in range(numbits): + if val & (1 << i) != 0: + self.Emit1(1) + else: + self.Emit1(0) + def writeWord(self): + bts = struct.pack('<I', self.u32) + self.f.write(bts) + self.u32 = 0 + self.curpos = 0 + def flush(self): + if self.curpos != 0: + self.writeWord() + +class BitcodeWriter: + def __init__(self): + pass + def WriteModule(self, module): + pass + def WriteModuleToFile(self, module, f): + s = BitstreamWriter(f) + s.Emit(ord('B'), 8) + s.Emit(ord('C'), 8) + s.Emit(0x0, 4) + s.Emit(0xC, 4) + s.Emit(0xE, 4) + s.Emit(0xD, 4) + self.WriteModule(module) + s.flush() +