changeset 389:2ec730e45ea1

Added check for recursive struct
author Windel Bouwman
date Fri, 16 May 2014 12:29:31 +0200
parents e07c2a9abac1
children a139da1f44f6
files kernel/arch/qemu_m3/startup_m3.asm kernel/arch/qemu_vexpress/archmem.c3 kernel/arch/qemu_vexpress/layout.mmap kernel/arch/qemu_vexpress/start.asm kernel/arch/qemu_vexpress/startup_a9.asm kernel/arch/qemu_vexpress/vexpressA9.c3 kernel/arch/qemu_vexpress/vexpressA9.mmap kernel/arch/vexpressA9.c3 kernel/build.xml kernel/src/memory.c3 kernel/src/process.c3 kernel/startup_m3.asm python/ppci/c3/astnodes.py python/ppci/c3/codegenerator.py python/ppci/c3/scope.py test/testarmasm.py test/testc3.py
diffstat 17 files changed, 369 insertions(+), 206 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/arch/qemu_m3/startup_m3.asm	Fri May 16 12:29:31 2014 +0200
@@ -0,0 +1,6 @@
+
+
+DCD 0x20000678  ; Setup stack pointer
+DCD 0x08000009  ; Reset vector, jump to address 8
+B kernel_start          ; Branch to main (this is actually in the interrupt vector)
+
--- a/kernel/arch/qemu_vexpress/archmem.c3	Fri May 02 14:51:46 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-module archmem;
-import io;
-
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/arch/qemu_vexpress/layout.mmap	Fri May 16 12:29:31 2014 +0200
@@ -0,0 +1,12 @@
+
+MEMORY image LOCATION=0x10000 SIZE=0x10000 {
+    SECTION(reset)
+    SECTION(code)
+    ALIGN(0x4000)
+    SECTION(mem_tables)
+}
+
+MEMORY ram LOCATION=0x20000 SIZE=0x10000 {
+    SECTION(data)
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/arch/qemu_vexpress/start.asm	Fri May 16 12:29:31 2014 +0200
@@ -0,0 +1,89 @@
+
+section reset
+
+interrupt_vector_table:
+ivt_reset: B start            ; 0x0 reset
+ivt_undef: B undef_handler    ; 0x4 undefined instruction
+ivt_svc: B undef_handler      ; 0x08 Supervisor call
+ivt_prefetch: B undef_handler ; 0x0C prefetch abort
+ivt_data: B undef_handler     ; 0x10 data abort
+ivt_hyptrap: B undef_handler  ; 0x14 not used
+ivt_irq: B undef_handler      ; 0x18 IRQ
+ivt_fiq: B undef_handler      ; 0x18 FIQ
+
+
+start:
+
+; Setup TTBR1 (translation table base register)
+
+ldr r0, =kernel_table0    ; pseudo instruction which loads the value of the symbol
+; -KERNEL_BASE
+mcr p15, 0, r0, c2, c0, 1 ; TTBR1
+mcr p15, 0, r0, c2, c0, 0 ; TTBR0
+
+; Prepare the TTBCR (translation table base control register)
+mov r0, 0x1  ; TBD: why set this to 1?
+mcr p15, 0, r0, c2, c0, 2
+
+
+; Set domain 0 to manager:
+mov r0, 3
+mcr p15, 0, r0, c3, c0, 0
+
+
+; Enable the VMSA (Virtual memory system architecture):
+mrc p15, 0, r0, c1, c0, 0
+; TODO:
+mov r1, 0x1
+orr r0, r0, r1 ; TODO: implement orr r0, r0, 1
+mcr p15, 0, r0, c1, c0, 0
+
+; Setup stack:
+mov sp, 0x30000
+BL kernel_start          ; Branch to main (this is actually in the interrupt vector)
+local_loop:
+B local_loop
+
+
+; Interrupt handlers:
+
+undef_handler:
+B undef_handler
+
+
+; Assembly language helpers:
+; Called to identify the proc:
+arch_pfr0:
+mrc p15, 0, r0, c0, c1, 0
+mov pc, lr
+
+arch_pfr1:
+mrc p15, 0, r0, c0, c1, 1
+mov pc, lr
+
+arch_mmfr0:
+mrc p15, 0, r0, c0, c1, 4
+mov pc, lr
+
+arch_mpuir:
+mrc p15, 0, r0, c0, c0, 4
+mov pc, lr
+
+
+; Memory map tables:
+
+section mem_tables
+
+kernel_table0:
+ dcd 0x00000402 ; Identity map first 1 MB
+ dcd 0x10000402 ; Map to peripheral space 1 MB
+ repeat 0x5FE
+ dcd 0
+ endrepeat
+
+ dcd 0x00000402 ; Alias to 0x0
+
+ repeat 0x9FF
+ dcd 0
+ endrepeat
+
--- a/kernel/arch/qemu_vexpress/startup_a9.asm	Fri May 02 14:51:46 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-
-section reset
-
-interrupt_vector_table:
-ivt_reset: B start  ; 0x0 reset
-ivt_undef: B undef_handler  ; 0x4 undefined instruction
-ivt_svc: B undef_handler  ; 0x08 Supervisor call
-ivt_prefetch: B undef_handler ; 0x0C prefetch abort
-ivt_data: B undef_handler  ; 0x10 data abort
-ivt_hyptrap: B undef_handler ; 0x14 not used
-ivt_irq: B undef_handler  ; 0x18 IRQ
-ivt_fiq: B undef_handler  ; 0x18 FIQ
-
-
-start:
-
-; Setup TTBR1 (translation table base register)
-
-ldr r0, =kernel_table0    ; pseudo instruction which loads the value of the symbol
-; -KERNEL_BASE
-mcr p15, 0, r0, c2, c0, 1 ; TTBR1
-mcr p15, 0, r0, c2, c0, 0 ; TTBR0
-
-; Prepare the TTBCR (translation table base control register)
-mov r0, 0x1  ; TBD: why set this to 1?
-mcr p15, 0, r0, c2, c0, 2
-
-
-; Set domain 0 to manager:
-mov r0, 3
-mcr p15, 0, r0, c3, c0, 0
-
-
-; Enable the VMSA (Virtual memory system architecture):
-mrc p15, 0, r0, c1, c0, 0
-; TODO:
-mov r1, 0x1
-orr r0, r0, r1 ; TODO: implement orr r0, r0, 1
-mcr p15, 0, r0, c1, c0, 0
-
-; Setup stack:
-mov sp, 0x30000
-BL kernel_start          ; Branch to main (this is actually in the interrupt vector)
-local_loop:
-B local_loop
-
-
-; Interrupt handlers:
-
-undef_handler:
-B undef_handler
-
-
-; Assembly language helpers:
-; Called to identify the proc:
-arch_pfr0:
-mrc p15, 0, r0, c0, c1, 0
-ldr r0, =kernel_table0
-mov pc, lr
-
-arch_pfr1:
-mrc p15, 0, r0, c0, c1, 1
-mov pc, lr
-
-arch_mmfr0:
-mrc p15, 0, r0, c0, c1, 4
-mov pc, lr
-
-
-arch_mpuir:
-mrc p15, 0, r0, c0, c0, 4
-mov pc, lr
-
-
-; Memory map tables:
-
-section mem_tables
-
-kernel_table0:
- dcd 0x00000402 ; Identity map first 1 MB
- dcd 0x10000402 ; Map to peripheral space 1 MB
- repeat 0x5FE
- dcd 0
- endrepeat
-
- dcd 0x00000402 ; Alias to 0x0
-
- repeat 0x9FF
- dcd 0
- endrepeat
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/arch/qemu_vexpress/vexpressA9.c3	Fri May 16 12:29:31 2014 +0200
@@ -0,0 +1,32 @@
+module arch;
+import io;
+
+
+function void init()
+{
+    // putc(65)
+    io.print2("PFR0 = ", pfr0());
+    io.print2("PFR1 = ", pfr1());
+    io.print2("MMFR0 = ", mmfr0());
+
+    // This below is not compatible with all qemu versions:
+    // io.print2("MPUIR = ", arch.mpuir());
+}
+
+function void putc(int c)
+{
+    var int *UART0DR;
+    UART0DR = cast<int*>(0x109000); // UART0 DR register when remapped at 1MB
+    *UART0DR = c;
+}
+
+function void halt()
+{
+    while(true) {}
+}
+
+function int pfr0();
+function int pfr1();
+function int mmfr0();
+// function int mpuir();
+
--- a/kernel/arch/qemu_vexpress/vexpressA9.mmap	Fri May 02 14:51:46 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-
-MEMORY image LOCATION=0x10000 SIZE=0x10000 {
-    SECTION(reset)
-    SECTION(code)
-    ALIGN(0x4000)
-    SECTION(mem_tables)
-}
-
-MEMORY ram LOCATION=0x20000 SIZE=0x10000 {
-    SECTION(data)
-}
-
--- a/kernel/arch/vexpressA9.c3	Fri May 02 14:51:46 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-module arch;
-import io;
-
-
-function void init()
-{
-    // putc(65)
-    io.print2("PFR0 = ", pfr0());
-    io.print2("PFR1 = ", pfr1());
-    io.print2("MMFR0 = ", mmfr0());
-
-    // This below is not compatible with all qemu versions:
-    // io.print2("MPUIR = ", arch.mpuir());
-}
-
-function void putc(int c)
-{
-    var int *UART0DR;
-    UART0DR = cast<int*>(0x109000); // UART0 DR register when remapped at 1MB
-    *UART0DR = c;
-}
-
-function void halt()
-{
-    while(true) {}
-}
-
-function int pfr0();
-function int pfr1();
-function int mmfr0();
-// function int mpuir();
-
--- a/kernel/build.xml	Fri May 02 14:51:46 2014 +0200
+++ b/kernel/build.xml	Fri May 16 12:29:31 2014 +0200
@@ -5,12 +5,12 @@
     <property name="arch" value="arm" />
 
     <target name="vexpress">
-        <assemble source="arch/qemu_vexpress/startup_a9.asm" target="arm" output="start.o" />
-        <compile target="arm" sources='arch/vexpressA9.c3' includes="${src}/*.c3" output="vexp.o" />
+        <assemble source="arch/qemu_vexpress/start.asm" target="arm" output="start.o" />
+        <compile target="arm" sources='arch/qemu_vexpress/vexpressA9.c3' includes="${src}/*.c3" output="vexp.o" />
         <compile target="arm" sources='${src}/*.c3' output="henkie.o" />
         <link output="kernel.o"
             target="arm"
-            layout="arch/qemu_vexpress/vexpressA9.mmap"
+            layout="arch/qemu_vexpress/layout.mmap"
             objects="henkie.o;vexp.o;start.o" />
         <objcopy
             objectfile="kernel.o"
--- a/kernel/src/memory.c3	Fri May 02 14:51:46 2014 +0200
+++ b/kernel/src/memory.c3	Fri May 16 12:29:31 2014 +0200
@@ -8,7 +8,7 @@
 function void init()
 {
     ptr = 0;
-    io.print2("ptr = ", ptr);
+    // io.print2("ptr = ", ptr);
     // TODO
 }
 
--- a/kernel/src/process.c3	Fri May 02 14:51:46 2014 +0200
+++ b/kernel/src/process.c3	Fri May 16 12:29:31 2014 +0200
@@ -7,19 +7,21 @@
 type struct {
     int id;
     int status;
+    process_t* next; // For linked list..
 } process_t;
 
 // Or, use this list structure:
 // List<process_t> procs;
 
 // init is the root of all processes:
-var process_t* init_pid;
+var process_t* root_process;
 var int next_pid;
 
 function void init()
 {
     next_pid = 0;
-    init_pid = Create();
+    root_process = cast<process_t*>(0);
+    // init_pid = Create();
 }
 
 /*
@@ -28,12 +30,36 @@
 function process_t* Create()
 {
     var process_t* p;
+    //TODO: implement alloc:
+
     //= memory.Alloc(sizeof(process_t));
     p->id = next_pid;
+    p->next = cast<process_t*>(0);
+
+    // Increment PID:
     next_pid = next_pid + 1;
+
+    // Store it in the list:
+    if (root_process == cast<process_t*>(0))
+    {
+        root_process = p;
+    }
+    else
+    {
+        var process_t* parent;
+        parent = root_process;
+        while (parent->next != cast<process_t*>(0))
+        {
+            parent = parent->next;
+        }
+        parent->next = p;
+    }
+
     return p;
 }
 
+// function
+
 
 function void Kill(process_t* p)
 {
--- a/kernel/startup_m3.asm	Fri May 02 14:51:46 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-
-
-DCD 0x20000678  ; Setup stack pointer
-DCD 0x08000009  ; Reset vector, jump to address 8
-B kernel_start          ; Branch to main (this is actually in the interrupt vector)
-
--- a/python/ppci/c3/astnodes.py	Fri May 02 14:51:46 2014 +0200
+++ b/python/ppci/c3/astnodes.py	Fri May 16 12:29:31 2014 +0200
@@ -5,8 +5,6 @@
 Finally code is generated from it.
 """
 
-from ppci import SourceLocation
-
 
 class Node:
     """ Base class of all nodes in a AST """
@@ -42,6 +40,10 @@
         if isinstance(decl, Function):
             decl.package = self
 
+    @property
+    def Types(self):
+        return self.innerScope.Types
+
     def __repr__(self):
         return 'MODULE {}'.format(self.name)
 
@@ -96,6 +98,9 @@
         self.name = name
         self.typ = typ
 
+    def __repr__(self):
+        return 'Member {}'.format(self.name)
+
 
 class StructureType(Type):
     """ Struct type consisting of several named members """
--- a/python/ppci/c3/codegenerator.py	Fri May 02 14:51:46 2014 +0200
+++ b/python/ppci/c3/codegenerator.py	Fri May 16 12:29:31 2014 +0200
@@ -35,12 +35,17 @@
         self.pkg = pkg
         self.intType = pkg.scope['int']
         self.boolType = pkg.scope['bool']
-        self.logger.debug('Generating ir-code for {}'.format(pkg.name), extra={'c3_ast':pkg})
+        self.pointerSize = 4
+        self.logger.debug('Generating ir-code for {}'.format(pkg.name),
+                          extra={'c3_ast': pkg})
         self.varMap = {}    # Maps variables to storage locations.
         self.m = ir.Module(pkg.name)
         try:
+            for typ in pkg.Types:
+                self.check_type(typ)
             # Only generate function if function contains a body:
-            real_functions = list(filter(lambda f: f.body, pkg.innerScope.Functions))
+            real_functions = list(filter(
+                lambda f: f.body, pkg.innerScope.Functions))
             for v in pkg.innerScope.Variables:
                 v2 = ir.GlobalVariable(v.name)
                 self.varMap[v] = v2
@@ -68,7 +73,7 @@
         # generate room for locals:
 
         for sym in fn.innerScope:
-            self.the_type(sym.typ)
+            self.check_type(sym.typ)
             if sym.isParameter:
                 p = ir.Parameter(sym.name)
                 variable = ir.LocalVariable(sym.name + '_copy')
@@ -110,11 +115,13 @@
         elif type(code) is ast.Assignment:
             lval = self.genExprCode(code.lval)
             rval = self.genExprCode(code.rval)
-            if not self.equalTypes(code.lval.typ, code.rval.typ):
-                msg = 'Cannot assign {} to {}'.format(code.rval.typ, code.lval.typ)
-                raise SemanticError(msg, code.loc)
+            if not self.equal_types(code.lval.typ, code.rval.typ):
+                raise SemanticError('Cannot assign {} to {}'
+                                    .format(code.rval.typ, code.lval.typ),
+                                    code.loc)
             if not code.lval.lvalue:
-                raise SemanticError('No valid lvalue {}'.format(code.lval), code.lval.loc)
+                raise SemanticError('No valid lvalue {}'.format(code.lval),
+                                    code.lval.loc)
             self.emit(ir.Move(lval, rval))
         elif type(code) is ast.ExpressionStatement:
             self.emit(ir.Exp(self.genExprCode(code.ex)))
@@ -170,27 +177,28 @@
             if expr.op == 'or':
                 l2 = self.newBlock()
                 self.gen_cond_code(expr.a, bbtrue, l2)
-                if not self.equalTypes(expr.a.typ, self.boolType):
+                if not self.equal_types(expr.a.typ, self.boolType):
                     raise SemanticError('Must be boolean', expr.a.loc)
                 self.setBlock(l2)
                 self.gen_cond_code(expr.b, bbtrue, bbfalse)
-                if not self.equalTypes(expr.b.typ, self.boolType):
+                if not self.equal_types(expr.b.typ, self.boolType):
                     raise SemanticError('Must be boolean', expr.b.loc)
             elif expr.op == 'and':
                 l2 = self.newBlock()
                 self.gen_cond_code(expr.a, l2, bbfalse)
-                if not self.equalTypes(expr.a.typ, self.boolType):
+                if not self.equal_types(expr.a.typ, self.boolType):
                     self.error('Must be boolean', expr.a.loc)
                 self.setBlock(l2)
                 self.gen_cond_code(expr.b, bbtrue, bbfalse)
-                if not self.equalTypes(expr.b.typ, self.boolType):
+                if not self.equal_types(expr.b.typ, self.boolType):
                     raise SemanticError('Must be boolean', expr.b.loc)
             elif expr.op in ['==', '>', '<', '!=', '<=', '>=']:
                 ta = self.genExprCode(expr.a)
                 tb = self.genExprCode(expr.b)
-                if not self.equalTypes(expr.a.typ, expr.b.typ):
+                if not self.equal_types(expr.a.typ, expr.b.typ):
                     raise SemanticError('Types unequal {} != {}'
-                               .format(expr.a.typ, expr.b.typ), expr.loc)
+                                        .format(expr.a.typ, expr.b.typ),
+                                        expr.loc)
                 self.emit(ir.CJump(ta, expr.op, tb, bbtrue, bbfalse))
             else:
                 raise SemanticError('non-bool: {}'.format(expr.op), expr.loc)
@@ -205,7 +213,7 @@
             raise NotImplementedError('Unknown cond {}'.format(expr))
 
         # Check that the condition is a boolean value:
-        if not self.equalTypes(expr.typ, self.boolType):
+        if not self.equal_types(expr.typ, self.boolType):
             self.error('Condition must be boolean', expr.loc)
 
     def genExprCode(self, expr):
@@ -216,8 +224,8 @@
             if expr.op in ['+', '-', '*', '/', '<<', '>>', '|', '&']:
                 ra = self.genExprCode(expr.a)
                 rb = self.genExprCode(expr.b)
-                if self.equalTypes(expr.a.typ, self.intType) and \
-                        self.equalTypes(expr.b.typ, self.intType):
+                if self.equal_types(expr.a.typ, self.intType) and \
+                        self.equal_types(expr.b.typ, self.intType):
                     expr.typ = expr.a.typ
                 else:
                     raise SemanticError('Can only add integers', expr.loc)
@@ -268,7 +276,8 @@
                     expr.typ = basetype.fieldType(expr.field)
                 else:
                     raise SemanticError('{} does not contain field {}'
-                                        .format(basetype, expr.field), expr.loc)
+                                        .format(basetype, expr.field),
+                                        expr.loc)
             else:
                 raise SemanticError('Cannot select {} of non-structure type {}'
                                     .format(expr.field, basetype), expr.loc)
@@ -283,10 +292,13 @@
             idx = self.genExprCode(expr.i)
             base_typ = self.the_type(expr.base.typ)
             if not isinstance(base_typ, ast.ArrayType):
-                raise SemanticError('Cannot index non-array type {}'.format(base_typ), expr.base.loc)
+                raise SemanticError('Cannot index non-array type {}'
+                                    .format(base_typ),
+                                    expr.base.loc)
             idx_type = self.the_type(expr.i.typ)
-            if not self.equalTypes(idx_type, self.intType):
-                raise SemanticError('Index must be int not {}'.format(idx_type), expr.i.loc)
+            if not self.equal_types(idx_type, self.intType):
+                raise SemanticError('Index must be int not {}'
+                                    .format(idx_type), expr.i.loc)
             assert type(base) is ir.Mem
             element_type = self.the_type(base_typ.element_type)
             element_size = self.size_of(element_type)
@@ -296,14 +308,18 @@
             return ir.Mem(ir.Add(base.e, ir.Mul(idx, ir.Const(element_size))))
         elif type(expr) is ast.Literal:
             expr.lvalue = False
-            typemap = {int: 'int', float: 'double', bool: 'bool', str:'string'}
+            typemap = {int: 'int',
+                       float: 'double',
+                       bool: 'bool',
+                       str: 'string'}
             if type(expr.val) in typemap:
                 expr.typ = self.pkg.scope[typemap[type(expr.val)]]
             else:
-                raise SemanticError('Unknown literal type {}'.format(expr.val), expr.loc)
+                raise SemanticError('Unknown literal type {}'
+                                    .format(expr.val), expr.loc)
             # Construct correct const value:
             if type(expr.val) is str:
-                cval = struct.pack('<I', len(expr.val)) + expr.val.encode('ascii')
+                cval = self.pack_string(expr.val)
                 return ir.Addr(ir.Const(cval))
             else:
                 return ir.Const(expr.val)
@@ -314,19 +330,26 @@
         else:
             raise NotImplementedError('Unknown expr {}'.format(expr))
 
+    def pack_string(self, txt):
+        """ Pack a string using 4 bytes length followed by text data """
+        length = struct.pack('<I', len(txt))
+        data = txt.encode('ascii')
+        return length + data
+
     def gen_type_cast(self, expr):
         """ Generate code for type casting """
         ar = self.genExprCode(expr.a)
         from_type = self.the_type(expr.a.typ)
         to_type = self.the_type(expr.to_type)
-        if isinstance(from_type, ast.PointerType) and isinstance(to_type, ast.PointerType):
-            expr.typ = expr.to_type
-            return ar
-        elif self.equalTypes(self.intType, from_type) and \
+        if isinstance(from_type, ast.PointerType) and \
                 isinstance(to_type, ast.PointerType):
             expr.typ = expr.to_type
             return ar
-        elif self.equalTypes(self.intType, to_type) \
+        elif self.equal_types(self.intType, from_type) and \
+                isinstance(to_type, ast.PointerType):
+            expr.typ = expr.to_type
+            return ar
+        elif self.equal_types(self.intType, to_type) \
                 and isinstance(from_type, ast.PointerType):
             expr.typ = expr.to_type
             return ar
@@ -351,11 +374,12 @@
         ptypes = ftyp.parametertypes
         if len(expr.args) != len(ptypes):
             raise SemanticError('{} requires {} arguments, {} given'
-                       .format(fname, len(ptypes), len(expr.args)), expr.loc)
+                                .format(fname, len(ptypes), len(expr.args)),
+                                expr.loc)
         for arg, at in zip(expr.args, ptypes):
-            if not self.equalTypes(arg.typ, at):
+            if not self.equal_types(arg.typ, at):
                 raise SemanticError('Got {}, expected {}'
-                           .format(arg.typ, at), arg.loc)
+                                    .format(arg.typ, at), arg.loc)
         # determine return type:
         expr.typ = ftyp.returntype
         return ir.Call(fname, args)
@@ -394,21 +418,21 @@
             return sum(self.size_of(mem.typ) for mem in t.mems)
         elif type(t) is ast.ArrayType:
             return t.size * self.size_of(t.element_type)
+        elif type(t) is ast.PointerType:
+            return self.pointerSize
         else:
             raise NotImplementedError(str(t))
 
-    def the_type(self, t):
-        """ Recurse until a 'real' type is found """
+    def the_type(self, t, reveil_defined=True):
+        """ Recurse until a 'real' type is found
+            When reveil_defined is True, defined types are resolved to
+            their backing types.
+        """
         if type(t) is ast.DefinedType:
-            t = self.the_type(t.typ)
+            if reveil_defined:
+                t = self.the_type(t.typ)
         elif type(t) in [ast.Identifier, ast.Member]:
-            t = self.the_type(self.resolveSymbol(t))
-        elif type(t) is ast.StructureType:
-            # Setup offsets of fields. Is this the right place?:
-            offset = 0
-            for mem in t.mems:
-                mem.offset = offset
-                offset = offset + self.size_of(mem.typ)
+            t = self.the_type(self.resolveSymbol(t), reveil_defined)
         elif isinstance(t, ast.Type):
             pass
         else:
@@ -416,24 +440,75 @@
         assert isinstance(t, ast.Type)
         return t
 
-    def equalTypes(self, a, b):
-        """ Compare types a and b for structural equavalence. """
+    def equal_types(self, a, b, byname=False):
+        """ Compare types a and b for structural equavalence.
+            if byname is True stop on defined types.
+        """
         # Recurse into named types:
-        a = self.the_type(a)
-        b = self.the_type(b)
+        a = self.the_type(a, not byname)
+        b = self.the_type(b, not byname)
 
+        # Check types for sanity:
+        self.check_type(a)
+        self.check_type(b)
+
+        # Do structural equivalence check:
         if type(a) is type(b):
             if type(a) is ast.BaseType:
                 return a.name == b.name
             elif type(a) is ast.PointerType:
-                return self.equalTypes(a.ptype, b.ptype)
+                # If a pointed type is detected, stop structural
+                # equivalence:
+                return self.equal_types(a.ptype, b.ptype, byname=True)
             elif type(a) is ast.StructureType:
                 if len(a.mems) != len(b.mems):
                     return False
-                return all(self.equalTypes(am.typ, bm.typ) for am, bm in
+                return all(self.equal_types(am.typ, bm.typ) for am, bm in
                            zip(a.mems, b.mems))
             elif type(a) is ast.ArrayType:
-                return self.equalTypes(a.element_type, b.element_type)
+                return self.equal_types(a.element_type, b.element_type)
+            elif type(a) is ast.DefinedType:
+                # Try by name in case of defined types:
+                return a.name == b.name
             else:
                 raise NotImplementedError('{} not implemented'.format(type(a)))
         return False
+
+    def check_type(self, t, first=True, byname=False):
+        """ Determine struct offsets and check for recursiveness by using
+            mark and sweep algorithm.
+            The calling function could call this function with first set
+            to clear the marks.
+        """
+
+        # Reset the mark and sweep:
+        if first:
+            self.got_types = set()
+
+        # Resolve the type:
+        t = self.the_type(t, not byname)
+
+        # Check for recursion:
+        if t in self.got_types:
+            raise SemanticError('Recursive data type {}'.format(t), None)
+
+        if type(t) is ast.BaseType:
+            pass
+        elif type(t) is ast.PointerType:
+            # If a pointed type is detected, stop structural
+            # equivalence:
+            self.check_type(t.ptype, first=False, byname=True)
+        elif type(t) is ast.StructureType:
+            self.got_types.add(t)
+            # Setup offsets of fields. Is this the right place?:
+            offset = 0
+            for struct_member in t.mems:
+                self.check_type(struct_member.typ, first=False)
+                struct_member.offset = offset
+                offset = offset + self.size_of(struct_member.typ)
+        elif type(t) is ast.ArrayType:
+            self.check_type(t.element_type, first=False)
+        elif type(t) is ast.DefinedType:
+            pass
+        else:
+            raise NotImplementedError('{} not implemented'.format(type(t)))
--- a/python/ppci/c3/scope.py	Fri May 02 14:51:46 2014 +0200
+++ b/python/ppci/c3/scope.py	Fri May 16 12:29:31 2014 +0200
@@ -20,6 +20,10 @@
         return sorted(syms, key=lambda v: v.name)
 
     @property
+    def Types(self):
+        return [s for s in self.Syms if isinstance(s, DefinedType)]
+
+    @property
     def Constants(self):
         return [s for s in self.Syms if type(s) is Constant]
 
@@ -81,6 +85,7 @@
     # Construct string type from others:
     ln = StructField('len', intType)
     txt = StructField('txt', ArrayType(byteType, 0))
-    strType = DefinedType('string', PointerType(StructureType([ln, txt])), None)
+    strType = DefinedType('string', PointerType(StructureType([ln, txt])),
+                          None)
     scope.addSymbol(strType)
     return scope
--- a/test/testarmasm.py	Fri May 02 14:51:46 2014 +0200
+++ b/test/testarmasm.py	Fri May 16 12:29:31 2014 +0200
@@ -80,7 +80,8 @@
         bgt sjakie
         beq sjakie
         bl sjakie""")
-        self.check('030000ea 020000da 010000ca 0000000a ffffffeb feffffea fdffffda fcffffca fbffff0a faffffeb')
+        self.check('030000ea 020000da 010000ca 0000000a ffffffeb feffffea \
+                    fdffffda fcffffca fbffff0a faffffeb')
 
     def testPush(self):
         self.feed('push {r11,r5,r4,lr}')
--- a/test/testc3.py	Fri May 02 14:51:46 2014 +0200
+++ b/test/testc3.py	Fri May 16 12:29:31 2014 +0200
@@ -64,7 +64,7 @@
 
     def expectErrors(self, snippet, rows):
         """ Helper to test for expected errors on rows """
-        ircode = list(self.builder.build([io.StringIO(snippet)]))
+        list(self.builder.build([io.StringIO(snippet)]))
         actualErrors = [err.row for err in self.diag.diags]
         if rows != actualErrors:
             self.diag.printErrors()
@@ -106,7 +106,7 @@
         snip = """module C;
         const int a = 2;
         """
-        i = self.expectOK(snip)
+        self.expectOK(snip)
 
     @unittest.skip('Not checked yet')
     def testConstantMutual(self):
@@ -118,7 +118,7 @@
           return b;
         }
         """
-        i = self.expectOK(snip)
+        self.expectOK(snip)
 
     def testPackageNotExists(self):
         p1 = """module p1;
@@ -506,6 +506,63 @@
         """
         self.expectErrors(snippet, [7])
 
+    def testLinkedList(self):
+        """
+            Test if a struct can contain a field with a pointer to itself
+        """
+        snippet = """
+         module testlinkedlist;
+
+         type struct {
+            int x;
+            list_t* next;
+         } list_t;
+
+         function void t()
+         {
+            var list_t* a;
+            a = a->next;
+         }
+        """
+        self.expectOK(snippet)
+
+    def testInfiniteStruct(self):
+        """
+            Test if a struct can contain a field with itself as type?
+            This should not be possible!
+        """
+        snippet = """
+         module testnestedstruct;
+
+         type struct {
+            int x;
+            list_t inner;
+         } list_t;
+
+        """
+        self.expectErrors(snippet, [0])
+
+    def testMutualStructs(self):
+        """
+            Test if two structs can contain each other!
+            This should not be possible!
+        """
+        snippet = """
+         module testnestedstruct;
+
+         type struct {
+            int x;
+            B other;
+         } A;
+
+         type struct {
+            int x;
+            A other;
+         } B;
+
+        """
+        self.expectErrors(snippet, [0])
+
     def testComplexType(self):
         snippet = """
          module testpointer;