# HG changeset patch # User Windel Bouwman # Date 1395257043 -3600 # Node ID c49459768aaa2a2d989af3e294f29a9a0fa90be0 # Parent 396e5cefba1320abd913b9db706fedefc2f08720 Work on globals diff -r 396e5cefba13 -r c49459768aaa kernel/src/kernel.c3 --- a/kernel/src/kernel.c3 Sun Mar 16 11:28:47 2014 +0100 +++ b/kernel/src/kernel.c3 Wed Mar 19 20:24:03 2014 +0100 @@ -10,8 +10,8 @@ function void do() { + G = G + 1; io.print2("G = ", G); - G = G + 1; } // Main entry point of the kernel: @@ -20,6 +20,7 @@ G = 0; arch.init(); + do(); io.println("Welcome to lcfos!"); do(); @@ -28,7 +29,7 @@ do(); io.print_int(0x1337); - //io.print_int(0x1338); + io.print_int(cast(&G)); //io.print2("Test: ", 0x13); var int a; diff -r 396e5cefba13 -r c49459768aaa python/ppci/c3/codegenerator.py --- a/python/ppci/c3/codegenerator.py Sun Mar 16 11:28:47 2014 +0100 +++ b/python/ppci/c3/codegenerator.py Wed Mar 19 20:24:03 2014 +0100 @@ -41,11 +41,11 @@ try: # Only generate function if function contains a body: real_functions = list(filter(lambda f: f.body, pkg.innerScope.Functions)) - #real_functions = list(filter(None, pkg.innerScope.Functions)) for v in pkg.innerScope.Variables: - self.varMap[v] = self.newTemp() + v2 = ir.GlobalVariable(v.name) + self.varMap[v] = v2 if not v.isLocal: - self.m.add_variable(v.name) + self.m.add_variable(v2) for s in real_functions: self.gen_function(s) except SemanticError as e: @@ -322,10 +322,14 @@ if isinstance(from_type, ast.PointerType) and isinstance(to_type, ast.PointerType): expr.typ = expr.to_type return ar - elif type(from_type) is ast.BaseType and from_type.name == 'int' and \ + elif self.equalTypes(self.intType, from_type) and \ isinstance(to_type, ast.PointerType): expr.typ = expr.to_type return ar + elif self.equalTypes(self.intType, to_type) \ + and isinstance(from_type, ast.PointerType): + expr.typ = expr.to_type + return ar elif type(from_type) is ast.BaseType and from_type.name == 'byte' and \ type(to_type) is ast.BaseType and to_type.name == 'int': expr.typ = expr.to_type diff -r 396e5cefba13 -r c49459768aaa python/ppci/codegen/canon.py --- a/python/ppci/codegen/canon.py Sun Mar 16 11:28:47 2014 +0100 +++ b/python/ppci/codegen/canon.py Wed Mar 19 20:24:03 2014 +0100 @@ -61,6 +61,9 @@ elif isinstance(exp, ir.LocalVariable): offset = frame.allocVar(exp) return ir.Add(frame.fp, ir.Const(offset)) + elif isinstance(exp, ir.GlobalVariable): + #frame.load_global_address(ir.label_name(exp)) + return exp elif isinstance(exp, ir.Mem): exp.e = rewriteExp(exp.e, frame) return exp @@ -74,7 +77,7 @@ return ir.Eseq(ir.Move(t, exp), t) else: raise NotImplementedError('NI: {}, {}'.format(exp, type(exp))) - + # The flatten functions pull out seq instructions to the sequence list. def flattenExp(exp): @@ -89,6 +92,8 @@ elif isinstance(exp, ir.Mem): exp.e, s = flattenExp(exp.e) return exp, s + elif isinstance(exp, ir.GlobalVariable): + return exp, [] elif isinstance(exp, ir.Addr): exp.e, s = flattenExp(exp.e) return exp, s diff -r 396e5cefba13 -r c49459768aaa python/ppci/codegen/codegen.py --- a/python/ppci/codegen/codegen.py Sun Mar 16 11:28:47 2014 +0100 +++ b/python/ppci/codegen/codegen.py Wed Mar 19 20:24:03 2014 +0100 @@ -51,6 +51,10 @@ def generate(self, ircode, outs): """ Generate code into output stream """ assert isinstance(ircode, ir.Module) + outs.select_section('data') + for global_variable in ircode.Variables: + print(global_variable) + self.target.emit_global(outs, ir.label_name(global_variable)) outs.select_section('code') # Munch program into a bunch of frames. One frame per function. diff -r 396e5cefba13 -r c49459768aaa python/ppci/ir.py --- a/python/ppci/ir.py Sun Mar 16 11:28:47 2014 +0100 +++ b/python/ppci/ir.py Wed Mar 19 20:24:03 2014 +0100 @@ -8,7 +8,7 @@ if isinstance(dut, Block): f = dut.function return label_name(f) + '_' + dut.name - elif isinstance(dut, Function): + elif isinstance(dut, Function) or isinstance(dut, GlobalVariable): return label_name(dut.module) + '_' + dut.name elif isinstance(dut, Module): return dut.name @@ -32,7 +32,9 @@ f.module = self def add_variable(self, v): + assert type(v) is GlobalVariable self.variables.append(v) + v.module = self def get_variables(self): return self.variables diff -r 396e5cefba13 -r c49459768aaa python/ppci/ir2tree.py --- a/python/ppci/ir2tree.py Sun Mar 16 11:28:47 2014 +0100 +++ b/python/ppci/ir2tree.py Wed Mar 19 20:24:03 2014 +0100 @@ -25,6 +25,12 @@ t.value = e return t +@register(ir.GlobalVariable) +def global_address_to_tree(e): + t = Tree('GLOBALADDRESS') + t.value = ir.label_name(e) + return t + @register(ir.Const) def const_to_tree(e): if type(e.value) is bytes: diff -r 396e5cefba13 -r c49459768aaa python/ppci/linker.py --- a/python/ppci/linker.py Sun Mar 16 11:28:47 2014 +0100 +++ b/python/ppci/linker.py Wed Mar 19 20:24:03 2014 +0100 @@ -113,10 +113,20 @@ offset = -offset U = 1 assert offset < 4096 - section.data[reloc.offset+2] |= (U << 6) #(rel24 >> 16) & 0xFF + section.data[reloc.offset+2] |= (U << 6) section.data[reloc.offset+1] |= (offset >> 8) & 0xF section.data[reloc.offset+0] = offset & 0xFF +@reloc('absaddr32') +def apply_absaddr32(reloc, sym, section, reloc_value): + assert sym.value % 4 == 0 + assert reloc_value % 4 == 0 + offset = sym.value + section.data[reloc.offset+3] = (offset >> 24) & 0xFF + section.data[reloc.offset+2] = (offset >> 16) & 0xFF + section.data[reloc.offset+1] = (offset >> 8) & 0xFF + section.data[reloc.offset+0] = offset & 0xFF + class Linker: """ Merges the sections of several object files and diff -r 396e5cefba13 -r c49459768aaa python/ppci/target/arm/__init__.py --- a/python/ppci/target/arm/__init__.py Sun Mar 16 11:28:47 2014 +0100 +++ b/python/ppci/target/arm/__init__.py Wed Mar 19 20:24:03 2014 +0100 @@ -1,5 +1,5 @@ -from ..basetarget import Target +from ..basetarget import Target, Label from ..arm.registers import R0, R1, R2, R3, R4, R5, R6, R7 from ..arm.registers import R8, R9, R10, R11, R12, SP, LR, PC from ..arm.registers import register_range @@ -33,6 +33,10 @@ self.add_lowering(And1, lambda im: And1(im.dst[0], im.src[0], im.src[1])) self.add_lowering(Mov1, lambda im: Mov1(im.dst[0], im.others[0])) + def emit_global(self, outs, lname): + outs.emit(Label(lname)) + outs.emit(Dcd(0)) + def make_parser(self): # Assembly grammar: self.add_keyword('r0') diff -r 396e5cefba13 -r c49459768aaa python/ppci/target/arm/arm.brg --- a/python/ppci/target/arm/arm.brg Sun Mar 16 11:28:47 2014 +0100 +++ b/python/ppci/target/arm/arm.brg Wed Mar 19 20:24:03 2014 +0100 @@ -2,12 +2,13 @@ from ppci.target.arm.instructions import Add1, Add2, Sub1, Mul1 from ppci.target.arm.instructions import Ldr1, Ldr3, Adr from ppci.target.arm.instructions import And1, Lsr1, Lsl1, Mov1 +from ppci.target.basetarget import LabelAddress %% %terminal ADDI32 SUBI32 MULI32 ADR %terminal ORI32 SHLI32 SHRI32 ANDI32 -%terminal CONSTI32 CONSTDATA MEMI32 REGI32 CALL +%terminal CONSTI32 CONSTDATA MEMI32 REGI32 CALL GLOBALADDRESS %terminal MOVI32 %% @@ -22,7 +23,7 @@ reg: MEMI32(ADDI32(reg, cn)) 2 'd = self.newTmp(); self.emit(Ldr1, dst=[d], src=[c0], others=[c1]); return d' reg: MEMI32(reg) 2 'd = self.newTmp(); self.emit(Ldr1, dst=[d], src=[c0], others=[0]); return d' - +reg: GLOBALADDRESS 21 'd = self.newTmp(); ln = self.selector.frame.add_constant(LabelAddress(tree.value)); self.emit(Ldr3, dst=[d], others=[ln]); return d' cn: CONSTI32 0 'return tree.value' diff -r 396e5cefba13 -r c49459768aaa python/ppci/target/arm/frame.py --- a/python/ppci/target/arm/frame.py Sun Mar 16 11:28:47 2014 +0100 +++ b/python/ppci/target/arm/frame.py Wed Mar 19 20:24:03 2014 +0100 @@ -1,5 +1,5 @@ from ... import ir -from ..basetarget import Label, Alignment +from ..basetarget import Label, Alignment, LabelAddress from ...irmach import AbstractInstruction, Frame from .instructions import Dcd, Add, Sub, Push, Pop, Mov, Db from .registers import R0, R1, R2, R3, R4, R5, R6, R7, R8, R11, LR, PC, SP @@ -52,7 +52,7 @@ return self.locVars[lvar] def add_constant(self, value): - assert type(value) in [int, bytes] + assert type(value) in [int, bytes, LabelAddress] lab_name = '{}_literal_{}'.format(self.name, len(self.constants)) self.constants.append((lab_name, value)) return lab_name @@ -84,6 +84,8 @@ for ln, v in self.constants: if isinstance(v, int): post.extend([Label(ln), Dcd(v)]) + elif isinstance(v, LabelAddress): + post.extend([Label(ln), Dcd(v)]) elif isinstance(v, bytes): post.append(Label(ln)) for c in v: diff -r 396e5cefba13 -r c49459768aaa python/ppci/target/arm/instructions.py --- a/python/ppci/target/arm/instructions.py Sun Mar 16 11:28:47 2014 +0100 +++ b/python/ppci/target/arm/instructions.py Wed Mar 19 20:24:03 2014 +0100 @@ -1,5 +1,5 @@ -from ..basetarget import Instruction +from ..basetarget import Instruction, LabelAddress from ...bitfun import rotate_left from .token import ArmToken @@ -31,17 +31,30 @@ assert isinstance(v, int) self.v = v - def __repr__(self): - return 'DCD {}'.format(hex(self.v)) - -class Dcd(ConstantData): +class Dcd(ArmInstruction): + def __init__(self, v): + super().__init__() + assert isinstance(v, int) or isinstance(v, LabelAddress) + self.v = v + def encode(self): - self.token[0:32] = self.v + if type(self.v) is int: + self.token[0:32] = self.v + else: + self.token[0:32] = 0 return self.token.encode() + def relocations(self): + if type(self.v) is LabelAddress: + return [(self.v.name, 'absaddr32')] + return [] + def __repr__(self): - return 'DCD {}'.format(hex(self.v)) + if type(self.v) is int: + return 'DCD {}'.format(hex(self.v)) + else: + return 'DCD ={}'.format(self.v.name) class Db(ConstantData): diff -r 396e5cefba13 -r c49459768aaa python/ppci/target/basetarget.py --- a/python/ppci/target/basetarget.py Sun Mar 16 11:28:47 2014 +0100 +++ b/python/ppci/target/basetarget.py Wed Mar 19 20:24:03 2014 +0100 @@ -74,6 +74,11 @@ self.name = name +class LabelAddress: + def __init__(self, name): + self.name = name + + class Target: def __init__(self, name, desc=''): self.name = name diff -r 396e5cefba13 -r c49459768aaa python/ppci/transform.py --- a/python/ppci/transform.py Sun Mar 16 11:28:47 2014 +0100 +++ b/python/ppci/transform.py Wed Mar 19 20:24:03 2014 +0100 @@ -131,6 +131,7 @@ child_nodes[ir.Mem] = ['e'] child_nodes[ir.Addr] = ['e'] child_nodes[ir.LocalVariable] = [] +child_nodes[ir.GlobalVariable] = [] child_nodes[ir.Parameter] = [] child_nodes[ir.Jump] = [] child_nodes[ir.Terminator] = [] diff -r 396e5cefba13 -r c49459768aaa test/testemulation.py --- a/test/testemulation.py Sun Mar 16 11:28:47 2014 +0100 +++ b/test/testemulation.py Wed Mar 19 20:24:03 2014 +0100 @@ -11,34 +11,45 @@ testdir = os.path.dirname(os.path.abspath(__file__)) def runQemu(kernel, machine='lm3s811evb'): - """ Runs qemu on a given kernel file on some machine """ + """ Runs qemu on a given kernel file """ + try: + os.remove('qemucontrol.sock') + except FileNotFoundError: + pass + + try: + os.remove('qemuserial.sock') + except FileNotFoundError: + pass + + # Listen to the control socket: + qemu_control = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + qemu_control.bind('qemucontrol.sock') + qemu_control.listen(0) + + # Listen to the serial output: + qemu_serial = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + qemu_serial.bind('qemuserial.sock') + qemu_serial.listen(0) + args = ['qemu-system-arm', '-M', machine, '-m', '16M', '-nographic', '-kernel', kernel, '-monitor', - 'unix:qemucontrol.sock,server', - '-serial', 'unix:qemuserial.sock,server'] - p = subprocess.Popen(args, stdout=subprocess.DEVNULL, - stderr=subprocess.DEVNULL) + 'unix:qemucontrol.sock', + '-serial', 'unix:qemuserial.sock', '-S'] + p = subprocess.Popen(args) + #stdout=subprocess.DEVNULL, + #stderr=subprocess.DEVNULL) # Give process some time to boot: - time.sleep(0.5) - - # Connect to the control socket: - qemu_control = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - qemu_control.connect('qemucontrol.sock') - - time.sleep(0.5) - - # Now connect to the serial output: - qemu_serial = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - qemu_serial.connect('qemuserial.sock') - - time.sleep(0.5) + qemu_serial, address_peer = qemu_serial.accept() + qemu_control, address_peer = qemu_control.accept() + qemu_control.send('cont\n'.encode('ascii')) qemu_serial.settimeout(0.2) # Receive all data: data = bytearray() - for i in range(40): + for i in range(400): try: data += qemu_serial.recv(1) except socket.timeout as e: @@ -48,10 +59,24 @@ # Send quit command: qemu_control.send("quit\n".encode('ascii')) - p.wait(timeout=3) + try: + p.wait(timeout=3) + except subprocess.TimeoutExpired: + p.kill() + print(p.communicate()) qemu_control.close() qemu_serial.close() + try: + os.remove('qemucontrol.sock') + except FileNotFoundError: + pass + + try: + os.remove('qemuserial.sock') + except FileNotFoundError: + pass + # Check that output was correct: return data diff -r 396e5cefba13 -r c49459768aaa test/testsamples.py --- a/test/testsamples.py Sun Mar 16 11:28:47 2014 +0100 +++ b/test/testsamples.py Wed Mar 19 20:24:03 2014 +0100 @@ -32,6 +32,34 @@ res = "".join("A = 0x{0:08X}\n".format(a) for a in range(10)) self.do(snippet, res) + def testForLoopPrint(self): + snippet = """ + module testglobal; + import io; + var int G; + function void do1() + { + G = G + 1; + io.print2("G=", G); + } + function void do5() + { + G = G + 5; + io.print2("G=", G); + } + function void start() + { + G = 0; + do1(); + do1(); + do2(); + do1(); + do2(); + } + """ + res = "".join("G=0x{0:08X}\n".format(a) for a in [1,2,7,8,13]) + self.do(snippet, res) + class TestSamplesOnVexpress(unittest.TestCase, Samples): def do(self, src, expected_output): @@ -53,8 +81,9 @@ }) runner.add_task(Compile()) runner.run_tasks() - res = runQemu() + res = runQemu('tst.bin', machine='vexpress-a9') self.assertEqual(expected_output, res) + if __name__ == '__main__': unittest.main() diff -r 396e5cefba13 -r c49459768aaa util/test_patterns.txt --- a/util/test_patterns.txt Sun Mar 16 11:28:47 2014 +0100 +++ b/util/test_patterns.txt Wed Mar 19 20:24:03 2014 +0100 @@ -56,4 +56,8 @@ === mrc p15, 0, r1, c2, c0, 0 mrc p14, 0, r1, c8, c7, 0 +=== +mov sp, =a +a: +.word 0