Mercurial > lcfOS
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;