Mercurial > lcfOS
changeset 219:1fa3e0050b49
Expanded ad hoc code generator
author | Windel Bouwman |
---|---|
date | Sat, 06 Jul 2013 12:38:09 +0200 |
parents | 494828a7adf1 |
children | 3f6c30a5d234 |
files | python/asm.py python/c3/parser.py python/codegenarm.py python/cortexm3.py python/ir/basicblock.py python/ir/instruction.py python/outstream.py python/stm32f4/blink.c3 python/target.py python/testasm.py python/transform.py python/zcc.py |
diffstat | 12 files changed, 362 insertions(+), 114 deletions(-) [+] |
line wrap: on
line diff
--- a/python/asm.py Fri Jul 05 15:30:22 2013 +0200 +++ b/python/asm.py Sat Jul 06 12:38:09 2013 +0200 @@ -137,7 +137,9 @@ self.emit = emitter self.p.parse(tokens) +# Pre construct parser to save time: asmParser = Parser() + class Assembler: def __init__(self, target=None): self.target = target
--- a/python/c3/parser.py Fri Jul 05 15:30:22 2013 +0200 +++ b/python/c3/parser.py Sat Jul 06 12:38:09 2013 +0200 @@ -41,14 +41,14 @@ return False def NextToken(self): - t = self.token - if t.typ != 'END': - self.token = self.tokens.__next__() - return t + t = self.token + if t.typ != 'END': + self.token = self.tokens.__next__() + return t def initLex(self, source): - self.tokens = lexer.tokenize(source) # Lexical stage - self.token = self.tokens.__next__() + self.tokens = lexer.tokenize(source) # Lexical stage + self.token = self.tokens.__next__() def addDeclaration(self, decl): self.currentPart.declarations.append(decl) @@ -88,7 +88,7 @@ # Type system def parseTypeSpec(self): # For now, do simple type spec, just parse an ID: - return self.parseDesignator() + #return self.parseDesignator() if self.Peak == 'struct': self.Consume('struct') self.Consume('{')
--- a/python/codegenarm.py Fri Jul 05 15:30:22 2013 +0200 +++ b/python/codegenarm.py Sat Jul 06 12:38:09 2013 +0200 @@ -4,7 +4,10 @@ from ppci import CompilerError class ArmCodeGenerator: - """ Simple code generator """ + """ + Simple code generator + Ad hoc implementation + """ def __init__(self, out): self.outs = out @@ -21,8 +24,14 @@ # TODO: use initial value: self.emit(arm.dcd_ins(0)) + self.imms = [] # list with immediates relative to PC. self.outs.selectSection('code') for f in ircode.Functions: + # Add global variable addresses to immediate list: + for gvar in ircode.Variables: + pass #self.imms.append(( + + self.stack_frame = [] self.emit(ALabel(f.name)) # Save some registers: self.emit(arm.push_ins(arm.RegisterSet({arm.r4, arm.r5, arm.r6,arm.r7,arm.lr}))) @@ -31,27 +40,67 @@ for ins in bb.Instructions: self.generateInstruction(ins) + self.outs.align(4) + while self.imms: + l, v = self.imms.pop() + self.emit(ALabel(l)) + self.emit(arm.dcd_ins(v)) + self.outs.align(4) + + def getStack(self, v): + off = self.stack_frame.index(v) + return off * 4 + def addStack(self, v): + self.stack_frame.append(v) + return self.getStack(v) + def getGlobal(self, r, g): + _global_address = g.name + '__global' + self.emit(arm.ldr_pcrel(r, ALabel(_global_address))) + def generateInstruction(self, ins): if type(ins) is ir.Branch: - self.emit(arm.jmp_ins(ins.target)) - elif type(ins) is ir.ImmLoad and ins.value < 255: - self.emit(arm.mov_ins(arm.r0, arm.Imm8(ins.value))) - # determine stack frame.. - self.emit(arm.mov_ins(arm.r1, arm.Imm8(9))) - #self.emit(arm. - elif type(ins) is ir.ImmLoad and ins.value < (2**32): - print(ins) + tgt = ALabel(ins.target.name) + self.emit(arm.jmp_ins(tgt)) + elif type(ins) is ir.ImmLoad: + lname = ins.target.name + '_ivalue' + self.emit(arm.ldr_pcrel(arm.r0, ALabel(lname))) + self.imms.append((lname, ins.value)) + self.emit(arm.str_sprel(arm.r0, self.addStack(ins.target))) elif type(ins) is ir.Store: - print(ins) - elif type(ins) is ir.Return: - self.emit(arm.pop_ins(arm.RegisterSet({arm.r5, arm.r6, arm.pc}))) + # Load value in r0: + self.emit(arm.ldr_sprel(arm.r0, self.getStack(ins.value))) + # store in memory: + self.getGlobal(arm.r1, ins.location) + self.emit(arm.storeimm5_ins(arm.r0, arm.MemoryOp(arm.r1, 0))) elif type(ins) is ir.Load: - print(ins) + self.getGlobal(arm.r0, ins.location) + self.emit(arm.loadimm5_ins(arm.r0, arm.MemoryOp(arm.r0, 0))) + # Store value on stack: + self.emit(arm.str_sprel(arm.r0, self.addStack(ins.value))) elif type(ins) is ir.BinaryOperator: - print(ins) + # Load operands: + self.emit(arm.ldr_sprel(arm.r0, self.getStack(ins.value1))) + self.emit(arm.ldr_sprel(arm.r1, self.getStack(ins.value2))) + # do operation: + if ins.operation == '+': + self.emit(arm.addregs_ins(arm.r0, arm.r0, arm.r1)) + else: + print('operation not implemented', ins.operation) + # Store value back: + self.emit(arm.str_sprel(arm.r0, self.addStack(ins.result))) + elif type(ins) is ir.Return: + self.emit(arm.pop_ins(arm.RegisterSet({arm.r4, arm.r5, arm.r6, arm.r7, arm.pc}))) elif type(ins) is ir.ConditionalBranch: - print(ins) + self.emit(arm.ldr_sprel(arm.r0, self.getStack(ins.a))) + self.emit(arm.ldr_sprel(arm.r1, self.getStack(ins.b))) self.emit(arm.cmp_ins(arm.r1, arm.r0)) + tgt_yes = ALabel(ins.lab1.name) + if ins.cond == '==': + self.emit(arm.beq_ins(tgt_yes)) + else: + print('TODO', ins.cond) + tgt_no = ALabel(ins.lab2.name) + self.emit(arm.jmp_ins(tgt_no)) else: raise CompilerError('IR "{}" not covered'.format(ins))
--- a/python/cortexm3.py Fri Jul 05 15:30:22 2013 +0200 +++ b/python/cortexm3.py Sat Jul 06 12:38:09 2013 +0200 @@ -1,6 +1,6 @@ import struct, types from target import Register, Instruction, Target, Imm8, Label, Imm3 -from asmnodes import ASymbol, ANumber, AUnop, ABinop +from asmnodes import ASymbol, ANumber, AUnop, ABinop, ALabel from ppci import CompilerError import ir @@ -36,6 +36,23 @@ if name in regs: r = regs[name] return cls(r.num) + +class Reg8Op: + def __init__(self, num): + assert num < 8 + self.num = num + + @classmethod + def Create(cls, vop): + if type(vop) is ASymbol: + name = vop.name + regs = {} + for r in armtarget.registers: + regs[r.name] = r + if name in regs: + r = regs[name] + if r.num < 8: + return cls(r.num) def getRegNum(n): for r in armtarget.registers: @@ -57,6 +74,9 @@ self.basereg = basereg self.offset = offset + def __repr__(self): + return '[{}, #{}]'.format(self.basereg, self.offset) + @classmethod def Create(cls, vop): if type(vop) is AUnop and vop.operation == '[]': @@ -77,7 +97,38 @@ else: return return cls(getRegNum(basereg.num), offset) - pass + +class MemoryOpReg8Imm5: + def __init__(self, basereg, offset): + assert type(basereg) is ArmReg + self.basereg = basereg + self.offset = offset + + def __repr__(self): + return '[{}, #{}]'.format(self.basereg, self.offset) + + @classmethod + def Create(cls, vop): + if type(vop) is AUnop and vop.operation == '[]': + vop = vop.arg # descent + if type(vop) is ABinop: + if vop.op == '+' and type(vop.arg1) is ASymbol and type(vop.arg2) is ANumber: + offset = vop.arg2.number + if offset > 120: + return + basereg = Reg8Op.Create(vop.arg1) + if not basereg: + return + else: + return + elif type(vop) is ASymbol: + offset = 0 + basereg = Reg8Op.Create(vop) + if not basereg: + return + else: + return + return cls(getRegNum(basereg.num), offset) class RegisterSet: def __init__(self, regs): @@ -129,10 +180,6 @@ armtarget.registers.append(r6) r7 = ArmReg(7, 'r7') armtarget.registers.append(r7) -r10 = ArmReg(10, 'r10') -armtarget.registers.append(r10) -r11 = ArmReg(11, 'r11') -armtarget.registers.append(r11) # Other registers: # TODO sp = ArmReg(13, 'sp') @@ -145,54 +192,104 @@ class ArmInstruction(Instruction): pass -class ldr_ins(ArmInstruction): - mnemonic = 'ldr' - opcode = 1337 - irpattern = 'todo' - class dcd_ins(ArmInstruction): mnemonic = 'dcd' def __init__(self, expr): self.expr = expr + def encode(self): return u32(self.expr) -@armtarget.instruction -class storeimm5_ins(ArmInstruction): - """ str Rt, [Rn, imm5], store value into memory """ - mnemonic = 'str' - operands = (RegOp, MemoryOp) + def __repr__(self): + return 'DCD 0x{0:X}'.format(self.expr) + + + +# Memory related + +class LS_imm5_base(ArmInstruction): + """ ??? Rt, [Rn, imm5] """ + operands = (Reg8Op, MemoryOpReg8Imm5) def __init__(self, rt, memop): assert memop.offset % 4 == 0 self.imm5 = memop.offset >> 2 self.rn = memop.basereg.num self.rt = rt.num + self.memloc = memop + assert self.rn < 8 + assert self.rt < 8 def encode(self): Rn = self.rn Rt = self.rt imm5 = self.imm5 - h = (0xC << 11) | (imm5 << 6) | (Rn << 3) | Rt + + h = (self.opcode << 11) | (imm5 << 6) | (Rn << 3) | Rt + return u16(h) + def __repr__(self): + return '{} {}, {}'.format(self.mnemonic, self.rt, self.memloc) + +@armtarget.instruction +class storeimm5_ins(LS_imm5_base): + mnemonic = 'STR' + opcode = 0xC + +@armtarget.instruction +class loadimm5_ins(LS_imm5_base): + mnemonic = 'LDR' + opcode = 0xD + +class ls_sp_base_imm8(ArmInstruction): + operands = (Reg8Op, MemoryOp) + def __init__(self, rt, memop): + self.rt = rt + assert memop.basereg.num == 13 + self.offset = memop.offset + + def encode(self): + rt = self.rt.num + assert rt < 8 + imm8 = self.offset >> 2 + assert imm8 < 256 + h = (self.opcode << 8) | (rt << 8) | imm8 return u16(h) + def __repr__(self): + return '{} {}, [sp,#{}]'.format(self.mnemonic, self.rt, self.offset) + @armtarget.instruction -class loadimm5_ins(ArmInstruction): - """ str Rt, [Rn, imm5], store value into memory """ +class ldr_pcrel(ArmInstruction): + """ ldr Rt, [PC, imm8], store value into memory """ mnemonic = 'ldr' operands = (RegOp, MemoryOp) - def __init__(self, rt, memop): - assert memop.offset % 4 == 0 - self.imm5 = memop.offset >> 2 - self.rn = memop.basereg.num - self.rt = rt.num + def __init__(self, rt, label): + self.rt = rt + self.label = label + self.offset = 0 def encode(self): - Rn = self.rn - Rt = self.rt - imm5 = self.imm5 - h = (0xD << 11) | (imm5 << 6) | (Rn << 3) | Rt + rt = self.rt.num + assert rt < 8 + imm8 = self.offset >> 2 + assert imm8 < 256 + h = (0x9 << 11) | (rt << 8) | imm8 return u16(h) + def __repr__(self): + return 'LDR {}, [pc,#{}]'.format(self.rt, self.offset) + +@armtarget.instruction +class ldr_sprel(ls_sp_base_imm8): + """ ldr Rt, [SP, imm8] """ + mnemonic = 'LDR' + opcode = 0x98 + +@armtarget.instruction +class str_sprel(ls_sp_base_imm8): + """ str Rt, [SP, imm8] """ + mnemonic = 'STR' + opcode = 0x90 + @armtarget.instruction class mov_ins(ArmInstruction): """ mov Rd, imm8, move immediate value into register """ @@ -204,22 +301,19 @@ self.imm = imm.imm self.r = rd.num - @classmethod - def FromIr(cls, ir_ins): - pass - def encode(self): rd = self.r opcode = self.opcode imm8 = self.imm h = (opcode << 11) | (rd << 8) | imm8 return u16(h) + def __repr__(self): + return 'MOV {0}, xx?'.format(self.r) @armtarget.instruction class movregreg_ins(ArmInstruction): """ mov Rd, Rm """ mnemonic = 'mov' - opcode = 8 # 01000 Rd(3) imm8 operands = (RegOp, RegOp) def __init__(self, rd, rm): self.rd = rd @@ -232,9 +326,13 @@ rm = self.rm.num assert rm < 16 opcode = self.opcode - h = (opcode << 11) | (3 << 9) | (D << 7) | (rm << 3) | rd + h = (1 << 14) | (3 << 9) | (D << 7) | (rm << 3) | rd return u16(h) + + +# Arithmatics: + @armtarget.instruction class addregregimm3_ins(ArmInstruction): """ add Rd, Rn, imm3 """ @@ -254,6 +352,61 @@ h = (opcode << 11) | (1 << 10) | (imm3 << 6) | (rn << 3) | rd return u16(h) +class regregreg_base(ArmInstruction): + """ ??? Rd, Rn, Rm """ + operands = (Reg8Op, Reg8Op, Reg8Op) + def __init__(self, rd, rn, rm): + self.rd = rd + self.rn = rn + self.rm = rm + def encode(self): + rd = self.rd.num + rn = self.rn.num + rm = self.rm.num + h = (self.opcode << 9) | (rm << 6) | (rn << 3) | rd + return u16(h) + def __repr__(self): + return '{} {}, {}, {}'.format(self.mnemonic, self.rd, self.rn, self.rm) + +@armtarget.instruction +class addregs_ins(regregreg_base): + mnemonic = 'ADD' + opcode = 0b0001100 + +@armtarget.instruction +class subregs_ins(regregreg_base): + mnemonic = 'SUB' + opcode = 0b0001101 + +class regreg_base(ArmInstruction): + """ ??? Rdn, Rm """ + operands = (Reg8Op, Reg8Op) + def __init__(self, rdn, rm): + self.rdn = rdn + self.rm = rm + def encode(self): + rdn = self.rdn.num + rm = self.rm.num + h = (self.opcode << 6) | (rm << 3) | rdn + return u16(h) + def __repr__(self): + return '{} {}, {}'.format(self.mnemonic, self.rdn, self.rm) + +@armtarget.instruction +class andregs_ins(regreg_base): + mnemonic = 'AND' + opcode = 0b0100000000 + +@armtarget.instruction +class orrregs_ins(regreg_base): + mnemonic = 'ORR' + opcode = 0b0100001100 + +@armtarget.instruction +class cmp_ins(regreg_base): + mnemonic = 'CMP' + opcode = 0b0100001010 + @armtarget.instruction class cmpregimm8_ins(ArmInstruction): """ cmp Rn, imm8 """ @@ -270,34 +423,37 @@ h = (opcode << 11) | (rn << 8) | imm return u16(h) -@armtarget.instruction -class cmp_ins(ArmInstruction): - """ cmp Rn, Rm """ - mnemonic = 'cmp' - operands = (RegOp, RegOp) - def __init__(self, rn, rm): - self.rn = rn - self.rm = rm - def encode(self): - rn = self.rn.num - rm = self.rm.num - assert rn < 8 - assert rm < 8 - opcode = 0x42 - h = (opcode << 8) | (1 << 7) | (rm << 3) | (rn & 0x7) - return u16(h) +# Jumping: @armtarget.instruction class jmp_ins(ArmInstruction): - operands = (Label,) + operands = (ALabel,) mnemonic = 'jmp' def __init__(self, target_label): + assert type(target_label) is ALabel self.target = target_label def fixUp(self): pass def encode(self): - h = 1337 # TODO + h = 0 # TODO return u16(h) + def __repr__(self): + return 'B {0}'.format(self.target.name) + +@armtarget.instruction +class beq_ins(ArmInstruction): + operands = (ALabel,) + mnemonic = 'beq' + def __init__(self, target_label): + assert type(target_label) is ALabel + self.target = target_label + def fixUp(self): + pass + def encode(self): + h = 0 # TODO + return u16(h) + def __repr__(self): + return 'BEQ {0}'.format(self.target.name) @armtarget.instruction class push_ins(ArmInstruction): @@ -341,7 +497,6 @@ raise NotImplementedError('not implemented for this register') h = (0x5E << 9) | (P << 8) | reg_list return u16(h) - return u16(0) @armtarget.instruction class yield_ins(ArmInstruction):
--- a/python/ir/basicblock.py Fri Jul 05 15:30:22 2013 +0200 +++ b/python/ir/basicblock.py Sat Jul 06 12:38:09 2013 +0200 @@ -1,60 +1,61 @@ class BasicBlock: - """ Uninterrupted sequence of instructions. """ - def __init__(self, name): + """ Uninterrupted sequence of instructions. """ + def __init__(self, name): self.name = name self.instructions = [] - def __repr__(self): + def __repr__(self): return 'BasicBlock {0}'.format(self.name) - def addInstruction(self, i): + def addInstruction(self, i): i.parent = self self.instructions.append(i) - addIns = addInstruction + addIns = addInstruction - def replaceInstruction(self, i1, i2): + def replaceInstruction(self, i1, i2): idx = self.instructions.index(i1) i1.parent = None i1.delete() i2.parent = self self.instructions[idx] = i2 - def removeInstruction(self, i): + def removeInstruction(self, i): i.parent = None self.instructions.remove(i) - def getInstructions(self): + def getInstructions(self): return self.instructions - def setInstructions(self, ins): + def setInstructions(self, ins): for i in self.instructions: i.parent = None self.instructions = ins for i in self.instructions: i.parent = self - Instructions = property(getInstructions, setInstructions) + Instructions = property(getInstructions, setInstructions) - def getLastIns(self): + def getLastIns(self): return self.instructions[-1] - LastInstruction = property(getLastIns) - @property - def Empty(self): + LastInstruction = property(getLastIns) + @property + def Empty(self): return len(self.instructions) == 0 - @property - def FirstInstruction(self): + @property + def FirstInstruction(self): return self.instructions[0] - FirstIns = FirstInstruction - def getSuccessors(self): + FirstIns = FirstInstruction + + def getSuccessors(self): if not self.Empty: i = self.LastInstruction - print(i) return i.Targets return [] - Successors = property(getSuccessors) - def getPredecessors(self): + Successors = property(getSuccessors) + + def getPredecessors(self): preds = [] for bb in self.parent.BasicBlocks: if self in bb.Successors: preds.append(bb) return preds - Predecessors = property(getPredecessors) + Predecessors = property(getPredecessors)
--- a/python/ir/instruction.py Fri Jul 05 15:30:22 2013 +0200 +++ b/python/ir/instruction.py Sat Jul 06 12:38:09 2013 +0200 @@ -156,17 +156,17 @@ # Branching: class Branch(Terminator): - def __init__(self, target): + def __init__(self, target): super().__init__() assert type(target) is BasicBlock self.target = target - def __repr__(self): - return 'BRANCH {0}'.format(self.target) - def getTargets(self): - return [self.target] - def changeTarget(self, tfrom, tto): - if tfrom is self.target: - self.target = tto + def __repr__(self): + return 'BRANCH {0}'.format(self.target) + def getTargets(self): + return [self.target] + def changeTarget(self, tfrom, tto): + assert tfrom is self.target + self.target = tto class ConditionalBranch(Terminator): def __init__(self, a, cond, b, lab1, lab2): @@ -187,9 +187,10 @@ def getTargets(self): return [self.lab1, self.lab2] def changeTarget(self, tfrom, tto): + assert tfrom is self.lab1 or tfrom is self.lab2 if tfrom is self.lab1: self.lab1 = tto - if tfrom is self.lab2: + elif tfrom is self.lab2: self.lab2 = tto class PhiNode(Instruction):
--- a/python/outstream.py Fri Jul 05 15:30:22 2013 +0200 +++ b/python/outstream.py Sat Jul 06 12:38:09 2013 +0200 @@ -5,12 +5,20 @@ to a file or binary or hexfile. """ +class Alignment: + def __init__(self, a): + self.align = a + class OutputStream: def __init__(self): self.sections = {} self.currentSection = None def emit(self, item): self.sections[self.currentSection].append(item) + + def align(self, alignment): + self.emit(Alignment(alignment)) + def selectSection(self, s): self.currentSection = s if not s in self.sections: @@ -30,6 +38,10 @@ i.address = address if type(i) is ALabel: continue + if type(i) is Alignment: + while (address % i.align) != 0: + address += 1 + continue bts = i.encode() address += len(bts) @@ -43,6 +55,8 @@ for i in self.sections[s]: if type(i) is ALabel: print(i) + elif type(i) is Alignment: + pass else: addr = i.address insword = i.encode()
--- a/python/stm32f4/blink.c3 Fri Jul 05 15:30:22 2013 +0200 +++ b/python/stm32f4/blink.c3 Sat Jul 06 12:38:09 2013 +0200 @@ -17,7 +17,7 @@ if (true) { divider = divider + 1; - if (divider > 100000) + if (divider == 100000) { divider = 0; //GPIOD->ODR ^= (1 << 13); @@ -28,6 +28,9 @@ function void main() { divider = 0; + + var int* RCC_AHB1ENR; + RCC_AHB1ENR = 0x40003022; /* RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN; RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
--- a/python/target.py Fri Jul 05 15:30:22 2013 +0200 +++ b/python/target.py Sat Jul 06 12:38:09 2013 +0200 @@ -93,7 +93,7 @@ # look for a suitable instruction for ic in self.instructions: - if ic.mnemonic == vi.mnemonic and len(ic.operands) == len(vi.operands): + if ic.mnemonic.upper() == vi.mnemonic.upper() and len(ic.operands) == len(vi.operands): # Try to map operands to the correct operand types: rops = [roptype.Create(vop) for roptype, vop in zip(ic.operands, vi.operands)]
--- a/python/testasm.py Fri Jul 05 15:30:22 2013 +0200 +++ b/python/testasm.py Sat Jul 06 12:38:09 2013 +0200 @@ -186,6 +186,16 @@ self.feed('ldr r4, [r0 + 0]') self.check('0468') + @unittest.skip + def testLdrSpRel(self): + self.feed('ldr r0, [sp + 4]') + self.check('0198') + + @unittest.skip + def testStrSpRel(self): + self.feed('str r0, [sp + 4]') + self.check('0190') + def testCmpRegReg(self): self.feed('cmp r0, r1') self.check('8842')
--- a/python/transform.py Fri Jul 05 15:30:22 2013 +0200 +++ b/python/transform.py Sat Jul 06 12:38:09 2013 +0200 @@ -78,19 +78,28 @@ return True class CleanPass(FunctionPass): - def onFunction(self, f): + def onFunction(self, f): bbs = list(f.BasicBlocks) for bb in bbs: # TODO: determine check for 'empty' + + # If a block only contains a branch, it can be removed: if len(bb.Instructions) == 1: # This block is empty. # find predecessors of this block and replace this block reference with the jumped reference. ins = bb.LastInstruction if type(ins) is Branch: - print(ins, bb.Predecessors) - for pred in bb.Predecessors: - pred.LastInstruction.changeTarget(bb, ins.target) - f.removeBasicBlock(bb) + print('Removing block {}'.format(bb)) + #print(ins, bb.Predecessors) + preds = bb.Predecessors + if bb in preds: + # Do not remove if preceeded by itself + pass + else: + for pred in bb.Predecessors: + print('predecessor: {}'.format(pred)) + pred.LastInstruction.changeTarget(bb, ins.target) + f.removeBasicBlock(bb) class Mem2RegPromotor(FunctionPass): def onFunction(self, f):
--- a/python/zcc.py Fri Jul 05 15:30:22 2013 +0200 +++ b/python/zcc.py Sat Jul 06 12:38:09 2013 +0200 @@ -3,6 +3,7 @@ import sys, argparse import c3, ppci, codegen import codegenarm +from transform import CleanPass import outstream # Parse arguments: @@ -24,9 +25,12 @@ diag.printErrors(src) sys.exit(1) + # Optimization passes: + cp = CleanPass() + cp.run(ircode) + if args.dumpir: ircode.dump() - # Code generation: #cg = codegen.CodeGenerator(arm_cm3.armtarget)