# HG changeset patch # User Windel Bouwman # Date 1400354260 -7200 # Node ID 6ae782a085e0a3fa21a3f36affc6fe92cd7c0b75 # Parent bb4289c84907d6c53d24c4c3dfab916aa076f233 Added init program diff -r bb4289c84907 -r 6ae782a085e0 kernel/build.xml --- a/kernel/build.xml Fri May 16 13:05:10 2014 +0200 +++ b/kernel/build.xml Sat May 17 21:17:40 2014 +0200 @@ -4,18 +4,32 @@ + - - - + + + + + + + + + + + + diff -r bb4289c84907 -r 6ae782a085e0 kernel/src/kernel.c3 --- a/kernel/src/kernel.c3 Fri May 16 13:05:10 2014 +0200 +++ b/kernel/src/kernel.c3 Sat May 17 21:17:40 2014 +0200 @@ -6,6 +6,9 @@ import arch; import io; +// Globals: +var process.process_t* init_proc; + // Main entry point of the kernel: function void start() @@ -13,15 +16,20 @@ io.println("Welcome to lcfos!"); arch.init(); - - // process.init(); + process.init(); memory.init(); - //Process proc = new process:Process(); + init_proc = process.Create(); + + // TODO: copy content into process?? + // Create a second process: + process.Create(); + + io.print2("init address ", cast(init_proc)); //scheduler:queue(proc); io.println("Kernel finished"); - arch.halt(); + panic(); } // Called in total stress: diff -r bb4289c84907 -r 6ae782a085e0 kernel/src/memory.c3 --- a/kernel/src/memory.c3 Fri May 16 13:05:10 2014 +0200 +++ b/kernel/src/memory.c3 Sat May 17 21:17:40 2014 +0200 @@ -5,17 +5,33 @@ var int ptr; +// Let the heap grow upwards.. + function void init() { - ptr = 0; - // io.print2("ptr = ", ptr); - // TODO + ptr = 0x80000; } -function u8* Alloc(int size) +function u8* alloc(int size) { + var int ptr2; + ptr2 = ptr; + + io.print2("alloc size ", size); + io.print2("alloc address ", ptr); + + // Increment new free point: ptr = ptr + size; - return cast(ptr); + return cast(ptr2); } +function void memcpy(u8* dst, u8* src, int size) +{ + // + var int i; + for (i = 0; i < size; i = i + 1) + { + *(dst + i) = *(src + i); + } +} diff -r bb4289c84907 -r 6ae782a085e0 kernel/src/process.c3 --- a/kernel/src/process.c3 Fri May 16 13:05:10 2014 +0200 +++ b/kernel/src/process.c3 Sat May 17 21:17:40 2014 +0200 @@ -15,6 +15,7 @@ // init is the root of all processes: var process_t* root_process; + var int next_pid; function void init() @@ -30,10 +31,10 @@ function process_t* Create() { var process_t* p; - //TODO: implement alloc: - //= memory.Alloc(sizeof(process_t)); + p = cast(memory.alloc(sizeof(process_t))); p->id = next_pid; + p->status = 0; // Ready! p->next = cast(0); // Increment PID: @@ -52,14 +53,13 @@ { parent = parent->next; } + parent->next = p; } return p; } -// function - function void Kill(process_t* p) { diff -r bb4289c84907 -r 6ae782a085e0 kernel/src/schedule.c3 --- a/kernel/src/schedule.c3 Fri May 16 13:05:10 2014 +0200 +++ b/kernel/src/schedule.c3 Sat May 17 21:17:40 2014 +0200 @@ -2,6 +2,7 @@ module scheduler; import process; +import arch; var process.process_t *current; diff -r bb4289c84907 -r 6ae782a085e0 kernel/src/syscall.c3 --- a/kernel/src/syscall.c3 Fri May 16 13:05:10 2014 +0200 +++ b/kernel/src/syscall.c3 Sat May 17 21:17:40 2014 +0200 @@ -9,6 +9,8 @@ import process; +/* System call numbers: +*/ const int SendMsg = 1; const int ReceiveMsg = 2; const int Reboot = 3; @@ -18,7 +20,7 @@ function void handle_system_call(int callId, int a, int b) { // Main entry, check what to do here - if (callId == 1) + if (callId == SendMsg) { handle_send_msg(); var process.process_t* proc; diff -r bb4289c84907 -r 6ae782a085e0 python/ppci/buildfunctions.py --- a/python/ppci/buildfunctions.py Fri May 16 13:05:10 2014 +0200 +++ b/python/ppci/buildfunctions.py Sat May 17 21:17:40 2014 +0200 @@ -16,8 +16,9 @@ from .target.target_list import targets from .outstream import BinaryAndLoggingStream from .objectfile import ObjectFile, load_object -from . import DiagnosticsManager, CompilerError -from .tasks import TaskError +from . import DiagnosticsManager +from .tasks import TaskError, TaskRunner +from .recipe import RecipeLoader def fix_target(tg): @@ -64,6 +65,23 @@ raise TaskError('Cannot use {} as layout'.format(l)) +def construct(buildfile, targets=[]): + recipe_loader = RecipeLoader() + try: + project = recipe_loader.load_file(buildfile) + except OSError: + raise TaskError('Could not construct {}'.format(buildfile)) + project = None + + if project: + runner = TaskRunner() + res = runner.run(project, targets) + else: + res = 1 + + return res + + def assemble(source, target): """ Invoke the assembler on the given source, returns an object containing the output. """ @@ -100,7 +118,7 @@ # Something went wrong, do not continue the code generation continue - d = {'ircode':ircode} + d = {'ircode': ircode} logger.debug('Verifying code {}'.format(ircode), extra=d) Verifier().verify(ircode) @@ -113,7 +131,7 @@ Verifier().verify(ircode) # Code generation: - d = {'ircode':ircode} + d = {'ircode': ircode} logger.debug('Starting code generation for {}'.format(ircode), extra=d) cg.generate(ircode, output_stream) @@ -132,4 +150,3 @@ linker = Linker(target) output_obj = linker.link(objects, layout) return output_obj - diff -r bb4289c84907 -r 6ae782a085e0 python/ppci/buildtasks.py --- a/python/ppci/buildtasks.py Fri May 16 13:05:10 2014 +0200 +++ b/python/ppci/buildtasks.py Sat May 17 21:17:40 2014 +0200 @@ -4,10 +4,8 @@ Task can depend upon one another. """ -import logging - from .tasks import Task, TaskError, register_task -from .buildfunctions import c3compile, link, assemble, fix_object +from .buildfunctions import c3compile, link, assemble, fix_object, construct from pyyacc import ParserException from . import CompilerError @@ -36,9 +34,17 @@ self.target.project.set_property(name, value) +@register_task("build") +class ConstructTask(Task): + """ Builds another build description file (build.xml) """ + def run(self): + project = self.get_argument('file') + construct(project) + + @register_task("assemble") class AssembleTask(Task): - """ Task that can runs the assembler over the source and enters the + """ Task that can runs the assembler over the source and enters the output into an object file """ def run(self): @@ -73,8 +79,8 @@ output = c3compile(sources, includes, target) # Store output: - with open(output_filename, 'w') as f: - output.save(f) + with open(output_filename, 'w') as output_file: + output.save(output_file) @register_task("link") @@ -92,8 +98,8 @@ raise TaskError(e.msg) # Store output: - with open(output_filename, 'w') as f: - output_obj.save(f) + with open(output_filename, 'w') as output_file: + output_obj.save(output_file) @register_task("objcopy") @@ -105,6 +111,5 @@ obj = fix_object(object_filename) image = obj.get_image(image_name) - with open(output_filename, 'wb') as f: - f.write(image) - + with open(output_filename, 'wb') as output_file: + output_file.write(image) diff -r bb4289c84907 -r 6ae782a085e0 python/ppci/c3/astnodes.py --- a/python/ppci/c3/astnodes.py Fri May 16 13:05:10 2014 +0200 +++ b/python/ppci/c3/astnodes.py Sat May 17 21:17:40 2014 +0200 @@ -207,6 +207,12 @@ self.loc = loc +class Sizeof(Expression): + def __init__(self, typ, loc): + super().__init__(loc) + self.query_typ = typ + + class Deref(Expression): def __init__(self, ptr, loc): super().__init__(loc) @@ -380,6 +386,15 @@ return 'IF-statement' +class Switch(Statement): + def __init__(self, condition, loc): + super().__init__(loc) + self.condition = condition + + def __repr__(self): + return 'Switch on {}'.format(self.condition) + + class While(Statement): def __init__(self, condition, statement, loc): super().__init__(loc) diff -r bb4289c84907 -r 6ae782a085e0 python/ppci/c3/codegenerator.py --- a/python/ppci/c3/codegenerator.py Fri May 16 13:05:10 2014 +0200 +++ b/python/ppci/c3/codegenerator.py Sat May 17 21:17:40 2014 +0200 @@ -113,8 +113,8 @@ elif type(code) is ast.Empty: pass elif type(code) is ast.Assignment: - lval = self.genExprCode(code.lval) - rval = self.genExprCode(code.rval) + lval = self.gen_expr_code(code.lval) + rval = self.gen_expr_code(code.rval) if not self.equal_types(code.lval.typ, code.rval.typ): raise SemanticError('Cannot assign {} to {}' .format(code.rval.typ, code.lval.typ), @@ -124,7 +124,7 @@ code.lval.loc) self.emit(ir.Move(lval, rval)) elif type(code) is ast.ExpressionStatement: - self.emit(ir.Exp(self.genExprCode(code.ex))) + self.emit(ir.Exp(self.gen_expr_code(code.ex))) elif type(code) is ast.If: bbtrue = self.newBlock() bbfalse = self.newBlock() @@ -138,7 +138,7 @@ self.emit(ir.Jump(te)) self.setBlock(te) elif type(code) is ast.Return: - re = self.genExprCode(code.expr) + re = self.gen_expr_code(code.expr) self.emit(ir.Move(self.fn.return_value, re)) self.emit(ir.Jump(self.fn.epiloog)) b = self.newBlock() @@ -167,6 +167,8 @@ self.genCode(code.final) self.emit(ir.Jump(bbtest)) self.setBlock(te) + elif type(code) is ast.Switch: + raise NotImplementedError('Unknown stmt {}'.format(code)) else: raise NotImplementedError('Unknown stmt {}'.format(code)) @@ -193,8 +195,8 @@ 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) + ta = self.gen_expr_code(expr.a) + tb = self.gen_expr_code(expr.b) if not self.equal_types(expr.a.typ, expr.b.typ): raise SemanticError('Types unequal {} != {}' .format(expr.a.typ, expr.b.typ), @@ -204,7 +206,7 @@ raise SemanticError('non-bool: {}'.format(expr.op), expr.loc) expr.typ = self.boolType elif type(expr) is ast.Literal: - self.genExprCode(expr) + self.gen_expr_code(expr) if expr.val: self.emit(ir.Jump(bbtrue)) else: @@ -216,17 +218,21 @@ if not self.equal_types(expr.typ, self.boolType): self.error('Condition must be boolean', expr.loc) - def genExprCode(self, expr): + def gen_expr_code(self, expr): """ Generate code for an expression. Return the generated ir-value """ assert isinstance(expr, ast.Expression) if type(expr) is ast.Binop: expr.lvalue = False if expr.op in ['+', '-', '*', '/', '<<', '>>', '|', '&']: - ra = self.genExprCode(expr.a) - rb = self.genExprCode(expr.b) + ra = self.gen_expr_code(expr.a) + rb = self.gen_expr_code(expr.b) if self.equal_types(expr.a.typ, self.intType) and \ self.equal_types(expr.b.typ, self.intType): expr.typ = expr.a.typ + elif self.equal_types(expr.b.typ, self.intType) and \ + type(expr.a.typ) is ast.PointerType: + # Special case for pointer arithmatic TODO: coerce! + expr.typ = expr.a.typ else: raise SemanticError('Can only add integers', expr.loc) else: @@ -234,7 +240,7 @@ return ir.Binop(ra, expr.op, rb) elif type(expr) is ast.Unop: if expr.op == '&': - ra = self.genExprCode(expr.a) + ra = self.gen_expr_code(expr.a) expr.typ = ast.PointerType(expr.a.typ) if not expr.a.lvalue: raise SemanticError('No valid lvalue', expr.a.loc) @@ -253,13 +259,13 @@ expr.lvalue = True return ir.Mem(self.varMap[tg]) elif isinstance(tg, ast.Constant): - c_val = self.genExprCode(tg.value) + c_val = self.gen_expr_code(tg.value) return self.evalConst(c_val) else: raise NotImplementedError(str(tg)) elif type(expr) is ast.Deref: # dereference pointer type: - addr = self.genExprCode(expr.ptr) + addr = self.gen_expr_code(expr.ptr) ptr_typ = self.the_type(expr.ptr.typ) expr.lvalue = True if type(ptr_typ) is ast.PointerType: @@ -268,7 +274,7 @@ else: raise SemanticError('Cannot deref non-pointer', expr.loc) elif type(expr) is ast.Member: - base = self.genExprCode(expr.base) + base = self.gen_expr_code(expr.base) expr.lvalue = expr.base.lvalue basetype = self.the_type(expr.base.typ) if type(basetype) is ast.StructureType: @@ -288,8 +294,8 @@ return ir.Mem(ir.Add(base.e, offset)) elif type(expr) is ast.Index: """ Array indexing """ - base = self.genExprCode(expr.base) - idx = self.genExprCode(expr.i) + base = self.gen_expr_code(expr.base) + idx = self.gen_expr_code(expr.i) base_typ = self.the_type(expr.base.typ) if not isinstance(base_typ, ast.ArrayType): raise SemanticError('Cannot index non-array type {}' @@ -325,6 +331,12 @@ return ir.Const(expr.val) elif type(expr) is ast.TypeCast: return self.gen_type_cast(expr) + elif type(expr) is ast.Sizeof: + # The type of this expression is int: + expr.typ = self.intType + self.check_type(expr.query_typ) + type_size = self.size_of(expr.query_typ) + return ir.Const(type_size) elif type(expr) is ast.FunctionCall: return self.gen_function_call(expr) else: @@ -338,7 +350,7 @@ def gen_type_cast(self, expr): """ Generate code for type casting """ - ar = self.genExprCode(expr.a) + ar = self.gen_expr_code(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 \ @@ -364,7 +376,7 @@ def gen_function_call(self, expr): """ Generate code for a function call """ # Evaluate the arguments: - args = [self.genExprCode(e) for e in expr.args] + args = [self.gen_expr_code(e) for e in expr.args] # Check arguments: tg = self.resolveSymbol(expr.proc) if type(tg) is not ast.Function: diff -r bb4289c84907 -r 6ae782a085e0 python/ppci/c3/lexer.py --- a/python/ppci/c3/lexer.py Fri May 16 13:05:10 2014 +0200 +++ b/python/ppci/c3/lexer.py Sat May 17 21:17:40 2014 +0200 @@ -8,8 +8,9 @@ keywords = ['and', 'or', 'not', 'true', 'false', 'else', 'if', 'while', 'for', 'return', + 'switch', 'case', 'default', 'function', 'var', 'type', 'const', - 'struct', 'cast', + 'struct', 'cast', 'sizeof', 'import', 'module'] diff -r bb4289c84907 -r 6ae782a085e0 python/ppci/c3/parser.py --- a/python/ppci/c3/parser.py Fri May 16 13:05:10 2014 +0200 +++ b/python/ppci/c3/parser.py Sat May 17 21:17:40 2014 +0200 @@ -5,7 +5,7 @@ from .astnodes import Return, While, If, Empty, For from .astnodes import FunctionType, Function, FormalParameter from .astnodes import StructureType, DefinedType, PointerType, ArrayType -from .astnodes import Constant, Variable +from .astnodes import Constant, Variable, Sizeof from .astnodes import StructField, Deref, Index from .astnodes import Package from .astnodes import Identifier @@ -227,6 +227,13 @@ no = self.Statement() if self.hasConsumed('else') else Empty() return If(condition, yes, no, loc) + def parse_switch(self): + loc = self.Consume('switch').loc + self.Consume('(') + condition = self.Expression() + self.Consume(')') + return Switch(condition, loc) + def parseWhile(self): loc = self.Consume('while').loc self.Consume('(') @@ -271,6 +278,8 @@ return self.parseWhile() elif self.Peak == 'for': return self.parse_for() + elif self.Peak == 'switch': + return self.parse_switch() elif self.Peak == '{': return self.parseCompound() elif self.hasConsumed(';'): @@ -376,9 +385,18 @@ ce = self.Expression() self.Consume(')') return TypeCast(t, ce, loc) + elif self.Peak == 'sizeof': + return self.sizeof_expression() else: return self.UnaryExpression() + def sizeof_expression(self): + loc = self.Consume('sizeof').loc + self.Consume('(') + typ = self.parse_type_spec() + self.Consume(')') + return Sizeof(typ, loc) + def UnaryExpression(self): if self.Peak in ['&', '*']: op = self.Consume(self.Peak) diff -r bb4289c84907 -r 6ae782a085e0 python/ppci/c3/visitor.py --- a/python/ppci/c3/visitor.py Fri May 16 13:05:10 2014 +0200 +++ b/python/ppci/c3/visitor.py Sat May 17 21:17:40 2014 +0200 @@ -60,6 +60,8 @@ elif type(node) is TypeCast: self.do(node.a) self.do(node.to_type) + elif type(node) is Sizeof: + self.do(node.query_typ) elif type(node) is Member: self.do(node.base) elif type(node) is Index: diff -r bb4289c84907 -r 6ae782a085e0 python/ppci/tasks.py --- a/python/ppci/tasks.py Fri May 16 13:05:10 2014 +0200 +++ b/python/ppci/tasks.py Sat May 17 21:17:40 2014 +0200 @@ -25,7 +25,7 @@ class Project: - """ A project contains a set of named targets that can depend upon + """ A project contains a set of named targets that can depend upon eachother """ def __init__(self, name): self.name = name @@ -67,7 +67,8 @@ target = self.get_target(target_name) for dep in target.dependencies: if dep in state: - raise TaskError('Dependency loop detected {} -> {}'.format(target_name, dep)) + raise TaskError('Dependency loop detected {} -> {}' + .format(target_name, dep)) self.dfs(dep, state) def check_target(self, target_name): @@ -195,4 +196,3 @@ self.logger.error(str(e.msg)) return 1 return 0 - diff -r bb4289c84907 -r 6ae782a085e0 python/zcc.py --- a/python/zcc.py Fri May 16 13:05:10 2014 +0200 +++ b/python/zcc.py Sat May 17 21:17:40 2014 +0200 @@ -4,10 +4,9 @@ import argparse import logging -from ppci.tasks import TaskRunner from ppci.report import RstFormatter -from ppci.recipe import RecipeLoader -import ppci.buildtasks # Include not used, but it registers build tasks. +from ppci.buildfunctions import construct +import ppci.buildtasks # Include not used, but it registers build tasks. import ppci @@ -48,14 +47,7 @@ fh.setFormatter(RstFormatter()) logging.getLogger().addHandler(fh) - recipe_loader = RecipeLoader() - try: - project = recipe_loader.load_file(args.buildfile) - except OSError as e: - res = 1 - - runner = TaskRunner() - res = runner.run(project, args.targets) + res = construct(args.buildfile, args.targets) if args.report: logging.getLogger().removeHandler(fh) diff -r bb4289c84907 -r 6ae782a085e0 test/testc3.py --- a/test/testc3.py Fri May 16 13:05:10 2014 +0200 +++ b/test/testc3.py Sat May 17 21:17:40 2014 +0200 @@ -392,7 +392,7 @@ module testarray; function void t() { - int c[20]; + var int c[20]; } """ self.expectErrors(snippet, [7]) @@ -418,12 +418,48 @@ print(a); print("Moi"); } + function void print(string a) { } """ self.expectOK(snippet) + def testSizeof1(self): + snippet = """ + module testsizeof; + + function void t() + { + var int a; + a = sizeof(int*); + } + """ + self.expectOK(snippet) + + def testSizeof2(self): + snippet = """ + module testsizeof2; + + function void t() + { + sizeof(int*) = 2; + } + """ + self.expectErrors(snippet, [6]) + + @unittest.skip('TODO: Too hard') + def testWrongVarUse(self): + snippet = """ + module testsizeof; + + function void t() + { + int a = 1; + } + """ + self.expectOK(snippet) + def testPointerType1(self): snippet = """ module testpointer1; @@ -494,6 +530,17 @@ """ self.expectOK(snippet) + def testPointerArithmatic(self): + snippet = """ + module testpointerarithmatic; + function void t() + { + var int* pa; + *(pa+2) = 2; + } + """ + self.expectOK(snippet) + def testWrongCast(self): snippet = """ module testptr_ir; diff -r bb4289c84907 -r 6ae782a085e0 user/build.xml --- a/user/build.xml Fri May 16 13:05:10 2014 +0200 +++ b/user/build.xml Sat May 17 21:17:40 2014 +0200 @@ -1,12 +1,32 @@ - - - - - + + + + + + + + + + + + + + + diff -r bb4289c84907 -r 6ae782a085e0 user/hello.c3 --- a/user/hello.c3 Fri May 16 13:05:10 2014 +0200 +++ b/user/hello.c3 Sat May 17 21:17:40 2014 +0200 @@ -7,6 +7,6 @@ function void start() { - lib.print(9); // 'Hello space'); + lib.print("Hello space"); } diff -r bb4289c84907 -r 6ae782a085e0 user/init.c3 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/user/init.c3 Sat May 17 21:17:40 2014 +0200 @@ -0,0 +1,12 @@ +module init; +import lib; + +/* +Initial program run by the system. +*/ + +function void start() +{ + lib.print("Welcome to lcfos"); +} + diff -r bb4289c84907 -r 6ae782a085e0 user/lib.c3 --- a/user/lib.c3 Fri May 16 13:05:10 2014 +0200 +++ b/user/lib.c3 Sat May 17 21:17:40 2014 +0200 @@ -3,14 +3,31 @@ /* Runtime library. - */ -function void print(int txt) +// Hack until something better exists: +function void putc(int c) +{ + var int *UART0DR; + UART0DR = cast(0x109000); // UART0 DR register when remapped at 1MB + *UART0DR = c; +} + +function void print(string txt) { // TODO var ipc.Msg msg; ipc.SendMessage(&msg); + + // TBD: send text to putc or via send message?? + var int i; + i = 0; + + while (i < txt->len) + { + putc(cast(txt->txt[i])); + i = i + 1; + } }