94
|
1 from .errors import CompilerException
|
105
|
2 from .module import Module
|
94
|
3 import struct
|
|
4
|
105
|
5 def enum(**enums):
|
|
6 return type('Enum', (), enums)
|
|
7
|
|
8 BitCodes = enum(END_BLOCK=0, ENTER_SUBBLOCK=1)
|
|
9
|
|
10 class BitstreamReader:
|
|
11 def __init__(self, f):
|
|
12 self.f = f
|
|
13 # Initialize the bitreader:
|
|
14 self.bitsInCurrent = 32
|
|
15 self.curWord = self.getWord()
|
|
16 self.curCodeSize = 2
|
|
17 def getWord(self):
|
|
18 bts = self.f.read(4)
|
|
19 return struct.unpack('<I', bts)[0]
|
|
20 def Read(self, numbits):
|
|
21 if numbits > 32:
|
|
22 raise CompilerException("Cannot read more than 32 bits")
|
|
23 if self.bitsInCurrent >= numbits:
|
|
24 # numbits inside the current word:
|
|
25 R = self.curWord & ((1 << numbits) - 1)
|
|
26 self.curWord = self.curWord >> numbits
|
|
27 self.bitsInCurrent -= numbits
|
|
28 return R
|
|
29 R = self.curWord
|
|
30 self.curWord = self.getWord()
|
|
31 bitsLeft = numbits - self.bitsInCurrent
|
|
32
|
|
33 # Add remaining bits:
|
|
34 R |= (self.curWord & (0xFFFFFFFF >> (32 - bitsLeft))) << self.bitsInCurrent
|
94
|
35
|
105
|
36 # Update curword and bits in current:
|
|
37 self.curWord = self.curWord >> bitsLeft
|
|
38 self.bitsInCurrent = 32 - bitsLeft
|
|
39 return R
|
|
40 def ReadVBR(self, numbits):
|
|
41 """ Read variable bits, checking for the last bit is zero. """
|
|
42 piece = self.Read(numbits)
|
|
43 if (piece & (1 << (numbits - 1))) == 0:
|
|
44 return piece
|
|
45 result = 0
|
|
46 nextbit = 0
|
|
47 while True:
|
|
48 mask = (1 << (numbits - 1)) - 1
|
|
49 result |= ( piece & mask ) << nextbit
|
|
50 if (piece & (1 << (numbits - 1))) == 0:
|
|
51 return result
|
|
52 nextbit += numbits - 1
|
|
53 piece = self.Read(numbits)
|
|
54 def ReadCode(self):
|
|
55 """ Read the code depending on the current code size """
|
|
56 return self.Read(self.curCodeSize)
|
|
57 def ReadSubBlockId(self):
|
|
58 return self.ReadVBR(8)
|
|
59 def EnterSubBlock(self, blockId):
|
|
60 pass
|
|
61
|
|
62 BLOCKINFO_BLOCKID = 0
|
|
63 FIRST_APPLICATION_BLOCKID = 8
|
|
64 MODULE_BLOCKID = FIRST_APPLICATION_BLOCKID
|
|
65
|
|
66 class BitcodeReader:
|
94
|
67 def __init__(self, f):
|
105
|
68 self.stream = BitstreamReader(f)
|
94
|
69 def parseModule(self):
|
105
|
70 for bitsig in [ord('B'), ord('C')]:
|
|
71 if self.stream.Read(8) != bitsig:
|
|
72 raise CompilerException('Invalid bitcode signature')
|
94
|
73 for bitsig in [0x0, 0xC, 0xE, 0xD]:
|
105
|
74 if self.stream.Read(4) != bitsig:
|
94
|
75 raise CompilerException('Invalid bitcode signature')
|
105
|
76 while True:
|
|
77 code = self.stream.ReadCode()
|
|
78 if code != BitCodes.ENTER_SUBBLOCK:
|
|
79 raise CompilerException('Invalid record at toplevel')
|
|
80 blockId = self.stream.ReadSubBlockId()
|
|
81 if blockId == MODULE_BLOCKID:
|
|
82 print('module block')
|
|
83 pass
|
|
84 else:
|
|
85 print('Block id:', blockId)
|
|
86 raise
|
|
87 return Module()
|
94
|
88
|
104
|
89 class BitstreamWriter:
|
|
90 def __init__(self, f):
|
|
91 self.f = f
|
|
92 self.u32 = 0
|
|
93 self.curpos = 0
|
|
94 def Emit1(self, val):
|
|
95 self.Emit(val, 1)
|
|
96 def Emit(self, val, numbits):
|
|
97 """ Emits value using numbits bits """
|
|
98 if numbits == 1:
|
|
99 if val != 0:
|
|
100 self.u32 |= (0x1 << self.curpos)
|
|
101 self.curpos += 1
|
|
102 if self.curpos == 32:
|
|
103 self.writeWord()
|
|
104 elif numbits > 1:
|
|
105 for i in range(numbits):
|
|
106 if val & (1 << i) != 0:
|
|
107 self.Emit1(1)
|
|
108 else:
|
|
109 self.Emit1(0)
|
|
110 def writeWord(self):
|
|
111 bts = struct.pack('<I', self.u32)
|
|
112 self.f.write(bts)
|
|
113 self.u32 = 0
|
|
114 self.curpos = 0
|
|
115 def flush(self):
|
|
116 if self.curpos != 0:
|
|
117 self.writeWord()
|
|
118
|
|
119 class BitcodeWriter:
|
|
120 def __init__(self):
|
|
121 pass
|
|
122 def WriteModule(self, module):
|
|
123 pass
|
|
124 def WriteModuleToFile(self, module, f):
|
|
125 s = BitstreamWriter(f)
|
|
126 s.Emit(ord('B'), 8)
|
|
127 s.Emit(ord('C'), 8)
|
|
128 s.Emit(0x0, 4)
|
|
129 s.Emit(0xC, 4)
|
|
130 s.Emit(0xE, 4)
|
|
131 s.Emit(0xD, 4)
|
|
132 self.WriteModule(module)
|
|
133 s.flush()
|
|
134
|