annotate python/ir/bitreader.py @ 160:10330be89bc2

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