changeset 364:c49459768aaa

Work on globals
author Windel Bouwman
date Wed, 19 Mar 2014 20:24:03 +0100
parents 396e5cefba13
children 98ff43cfdd36
files kernel/src/kernel.c3 python/ppci/c3/codegenerator.py python/ppci/codegen/canon.py python/ppci/codegen/codegen.py python/ppci/ir.py python/ppci/ir2tree.py python/ppci/linker.py python/ppci/target/arm/__init__.py python/ppci/target/arm/arm.brg python/ppci/target/arm/frame.py python/ppci/target/arm/instructions.py python/ppci/target/basetarget.py python/ppci/transform.py test/testemulation.py test/testsamples.py util/test_patterns.txt
diffstat 16 files changed, 158 insertions(+), 42 deletions(-) [+]
line wrap: on
line diff
--- 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<int>(&G));
     //io.print2("Test: ", 0x13);
 
     var int a;
--- 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
--- 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
--- 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.
--- 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
--- 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:
--- 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 
--- 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')
--- 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'
 
--- 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:
--- 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):
--- 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
--- 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] =  []
--- 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
 
--- 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()
--- 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