# HG changeset patch # User Windel Bouwman # Date 1356971717 -3600 # Node ID 6a303f835c6dea9992e7d3169316f7a3a49dbad7 # Parent ed230e947dc6319b9dd821a9b16632545b707002 Removed compilers directory diff -r ed230e947dc6 -r 6a303f835c6d python/bcanalyzer.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/python/bcanalyzer.py Mon Dec 31 17:35:17 2012 +0100 @@ -0,0 +1,19 @@ +#!/usr/bin/python + +import sys, os, argparse +from ppci.core import BitcodeReader + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description='Bitcode analyzer') + parser.add_argument('bitcodefile', type=str, help='the bitcode file to analyze') + args = parser.parse_args() + + try: + with open(args.bitcodefile, 'rb') as f: + bcr = BitcodeReader(f) + module = bcr.parseModule() + except IOError: + print('Failed to load {0}'.format(args.bitcodefile)) + sys.exit(3) + print(module) + diff -r ed230e947dc6 -r 6a303f835c6d python/hexviewer.py --- a/python/hexviewer.py Sun Dec 30 22:31:55 2012 +0100 +++ b/python/hexviewer.py Mon Dec 31 17:35:17 2012 +0100 @@ -26,16 +26,18 @@ br2 = QBrush(Qt.yellow) painter.setBrush(br2) w = self.width() - byteWidth = self.fontWidth * 16 * 3 + byteWidth = self.fontWidth * (16 * 3 - 1) painter.drawRect(addressWidth + 4, 2, byteWidth, h) asciiWidth = self.fontWidth * 16 br2 = QBrush(Qt.gray) painter.setBrush(br2) painter.drawRect(addressWidth + byteWidth + 4, 2, asciiWidth, h) - for r in range(1, 10): + rows = int(h / self.fontHeight) + 1 + offset = 0 + for r in range(1, rows): + bts = self.getBytes(offset + r - 1) addr = '{0:08X}'.format(r << 16) painter.drawText(2, 2 + self.fontHeight * r, addr) - bts = bytes(range(16)) x = addressWidth + 4 for b in bts: b = '{0:02X}'.format(b) @@ -46,8 +48,15 @@ b = '{0}'.format(chr(b)) painter.drawText(x, 2 + self.fontHeight * r, b) x += 1 * self.fontWidth + def getBytes(self, offset): + if self.hexfile.regions: + r = self.hexfile.regions[0] + chunks = [r.data[p:p+16] for p in range(0, len(r.data), 16)] + if len(chunks) > offset: + return chunks[offset] + return bytes() def setHexFile(self, hf): - self.hexFile = hf + self.hexfile = hf self.update() class BinViewMain(QMainWindow): @@ -55,7 +64,6 @@ super().__init__() self.bv = BinViewer() self.setCentralWidget(self.bv) - self.bv.setHexFile(hexfile.HexFile('audio.hex')) mb = self.menuBar() fileMenu = mb.addMenu("File") @@ -74,5 +82,6 @@ app = QApplication(sys.argv) bv = BinViewMain() bv.show() + bv.bv.setHexFile(hexfile.HexFile('audio.hex')) app.exec_() diff -r ed230e947dc6 -r 6a303f835c6d python/ppci/__init__.py --- a/python/ppci/__init__.py Sun Dec 30 22:31:55 2012 +0100 +++ b/python/ppci/__init__.py Mon Dec 31 17:35:17 2012 +0100 @@ -1,6 +1,4 @@ # File to make this directory a package. -from .compilers import KsCompiler - version = '0.0.1' diff -r ed230e947dc6 -r 6a303f835c6d python/ppci/compilers/__init__.py --- a/python/ppci/compilers/__init__.py Sun Dec 30 22:31:55 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -# File to make this directory a package. - -from .kscompiler import KsCompiler - diff -r ed230e947dc6 -r 6a303f835c6d python/ppci/compilers/kscompiler.py --- a/python/ppci/compilers/kscompiler.py Sun Dec 30 22:31:55 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -import hashlib -# Import compiler components: -from ..frontends.ks import KsParser -from ..frontends.ks import KsIrGenerator -#from .codegenerator import CodeGenerator -#from .nodes import ExportedSymbol -from ..core.errors import CompilerException -from ..core.bitreader import BitcodeWriter -from ..core import version, Context -#from .. import version - -class KsCompiler: - def __repr__(self): - return 'LCFOS compiler {0}'.format(version) - - def compilesource(self, src): - context = Context() - """ Front end that handles the stages: """ - self.errorlist = [] - # Pass 1: parsing and type checking - p = KsParser(src) - try: - ast = p.parseModule() # Parse a module into an AST - except CompilerException as e: - print(e) - p.errorlist.append( (e.row, e.col, e.msg) ) - if len(p.errorlist) > 0: - self.errorlist = p.errorlist - return - ir = KsIrGenerator().generateIr(context, ast) - # pass 2: Optimization - # TODO: implement optimization - - # Pass 3: code generation - return ast - diff -r ed230e947dc6 -r 6a303f835c6d python/ppci/core/__init__.py --- a/python/ppci/core/__init__.py Sun Dec 30 22:31:55 2012 +0100 +++ b/python/ppci/core/__init__.py Mon Dec 31 17:35:17 2012 +0100 @@ -1,7 +1,7 @@ from .instruction import * from .function import Function from .value import Value -from .bitreader import BitReader, BitcodeWriter +from .bitreader import BitcodeReader, BitcodeWriter from .errors import CompilerException from .module import Module from .llvmtype import FunctionType diff -r ed230e947dc6 -r 6a303f835c6d python/ppci/core/bitreader.py --- a/python/ppci/core/bitreader.py Sun Dec 30 22:31:55 2012 +0100 +++ b/python/ppci/core/bitreader.py Mon Dec 31 17:35:17 2012 +0100 @@ -1,30 +1,90 @@ from .errors import CompilerException +from .module import Module import struct -def bits(f): - while True: - Byte = f.read(1) - for i in range(8): - yield Byte & 0x1 - Byte >>= 1 +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(' 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 -class BitReader: + # 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 = bits(f) - self.curword = None + self.stream = BitstreamReader(f) def parseModule(self): - if self.read(8) != ord('B') or self.read(8) != ord('C'): - raise CompilerException('Invalid bitcode signature') + 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.read(4) != bitsig: + if self.stream.Read(4) != bitsig: raise CompilerException('Invalid bitcode signature') - - def read(self, numbits): - if numbits == 8: - b = self.stream.read(1) - print(b) - return int(b[0]) - return 2 + 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): diff -r ed230e947dc6 -r 6a303f835c6d python/ppci/core/function.py --- a/python/ppci/core/function.py Sun Dec 30 22:31:55 2012 +0100 +++ b/python/ppci/core/function.py Mon Dec 31 17:35:17 2012 +0100 @@ -1,7 +1,22 @@ + +class Argument: + def __init__(self, argtype, name, function): + self.t = argtype + self.name = name + self.function = function class Function: def __init__(self, functiontype, name, module): self.functiontype = functiontype self.name = name self.module = module + self.basicblocks = [] + self.arguments = [] + # Construct formal arguments depending on function type + + BasicBlocks = property(lambda self: self.basicblocks) + Arguments = property(lambda self: self.arguments) + ReturnType = property(lambda self: self.functiontype.returnType) + FunctionType = property(lambda self: self.functiontype) + diff -r ed230e947dc6 -r 6a303f835c6d python/ppci/core/module.py --- a/python/ppci/core/module.py Sun Dec 30 22:31:55 2012 +0100 +++ b/python/ppci/core/module.py Mon Dec 31 17:35:17 2012 +0100 @@ -1,7 +1,16 @@ from .value import Value +from .symboltable import SymbolTable class Module(Value): + """ + Main container for a piece of code. Contains globals and functions. + """ def __init__(self): - print('new module!') + self.functions = [] + self.globals_ = [] + self.symtable = SymbolTable() + + Globals = property(lambda self: self.globals_) + Functions = property(lambda self: self.functions) diff -r ed230e947dc6 -r 6a303f835c6d python/ppci/frontends/ks/__init__.py --- a/python/ppci/frontends/ks/__init__.py Sun Dec 30 22:31:55 2012 +0100 +++ b/python/ppci/frontends/ks/__init__.py Mon Dec 31 17:35:17 2012 +0100 @@ -1,13 +1,27 @@ -""" - Frontend for the K# language. - - This module can parse K# code and create LLVM intermediate code. -""" from .parser import KsParser from .irgenerator import KsIrGenerator class KsFrontend: - def __init__(self): - pass + """ + Frontend for the K# language. + This module can parse K# code and create LLVM intermediate code. + """ + def __init__(self, context): + self.context = context + def compilesource(self, src): + """ Front end that handles parsing and Module generation """ + self.errorlist = [] + # Pass 1: parsing and type checking + p = KsParser(src) + ast = p.parseModule() # Parse source into an AST + + # Store ast: + self.ast = ast + + # Generate ir (a core.Module): + ir = KsIrGenerator().generateIr(context, ast) + + return ir + diff -r ed230e947dc6 -r 6a303f835c6d python/zcc.py --- a/python/zcc.py Sun Dec 30 22:31:55 2012 +0100 +++ b/python/zcc.py Mon Dec 31 17:35:17 2012 +0100 @@ -1,26 +1,35 @@ #!/usr/bin/python import sys, os, argparse -from ppci.compilers import KsCompiler -from ppci.core import BitcodeWriter +from ppci import core + +parser = argparse.ArgumentParser(description='K# to bitcode compiler') +parser.add_argument('source', type=str, help='the source file to build') +args = parser.parse_args() -if __name__ == '__main__': - parser = argparse.ArgumentParser(description='K# to bitcode compiler') - parser.add_argument('source', type=str, help='the source file to build') - args = parser.parse_args() +try: + with open(args.source, 'r') as f: + src = f.read() +except IOError: + print('Failed to load {0}'.format(args.source)) + sys.exit(1) - print(args) - try: - with open(args.source, 'r') as f: - src = f.read() - except IOError: - print('Failed to load {0}'.format(args.project)) - sys.exit(3) - c = KsCompiler() - module = c.compilesource(src) +# Create a context and a frontend: +context = core.Context() +frontend = core.frontends.ks.KsFrontend(context) +try: + module = frontend.compilesource(src) +except core.CompilerException as e: + print(e) + sys.exit(2) - with open('sjaak.bc', 'wb') as f: - BitcodeWriter().WriteModuleToFile(module, f) +# optionally run passes here: +# TODO + +# Generate code: +bitcodeWriter = core.BitcodeWriter() +with open(args.source + '.bc', 'wb') as f: + bitcodeWriter.WriteModuleToFile(module, f)