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()
+