def visit_Assignment(self,node): lv = self.inFunctionDispatch(node.lvalue) rv = self.inFunctionDispatch(node.rvalue) self.assertNonVoid(lv) self.assertNonVoid(rv) if type(lv.type) == types.Array: raise Exception('cannot assign to an array') if rv.lval: rv = self.genDeref(rv) if not lv.type.strictTypeMatch(rv.type): rv = operatorgen.genCast(self.curBasicBlock,rv,lv.type) if not lv.lval: raise Exception("attemping to assign to a non lvalue!") if node.op in ['+=','-=' ,'/=','^=','|=','&=','*=','%=']: result = operatorgen.genBinop(self.curBasicBlock,node.op[0],lv,rv) else: if node.op != '=' : raise Exception("Bug - unknown assignment op %s" % node.op) result = rv self.curBasicBlock.append(ir.Store(lv.reg,result.reg)) return result
def visit_Switch(self,node): end = basicblock.BasicBlock() self.curBreakTargets.append(end) v = self.inFunctionDispatch(node.cond) self.assertNonVoid(v) if v.lval: v = self.genDeref(v) default = None bodies = [] for case in node.stmt.block_items: bodies.append(basicblock.BasicBlock()) for idx,case in enumerate(node.stmt.block_items): if type(case) == c_ast.Case: if type(case.expr) != c_ast.Constant: #XXX this needs to be proper const expressions raise Exception("non constant expression as case value") casev = self.inFunctionDispatch(case.expr) result = operatorgen.genBinop(self.curBasicBlock,'==',v,casev) nxt = basicblock.BasicBlock() self.curBasicBlock.append(ir.Branch(result.reg,bodies[idx],nxt)) self.curBasicBlock = nxt elif type(case) == c_ast.Default: if default != None: raise Exception("multiple defaults in case") default = bodies[idx] else: raise Exception("Non case or default in switch body") if self.curBasicBlock.unsafeEnding(): self.curBasicBlock.append(ir.Jmp(default)) #populate the bodies of each case for idx,case in enumerate(node.stmt.block_items): self.curBasicBlock = bodies[idx] try: fallthrough = bodies[idx+1] except IndexError: fallthrough = end for stmt in case.stmts: self.inFunctionDispatch(stmt) if self.curBasicBlock.unsafeEnding(): self.curBasicBlock.append(ir.Jmp(fallthrough)) self.curBasicBlock = end self.curBreakTargets.pop() print "end: ", self.curBasicBlock
def visit_Binop(self,node): lv = self.inFunctionDispatch(node.left) self.assertNonVoid(lv) # a short circuit binop requires some branches if node.op in ['&&', '||']: if lv.lval: lv = self.genDeref(lv) # lets just copy the input type for now, # it should probably do a cast or something constZero = lv.clone() result1 = lv.clone() result2 = lv.clone() result3 = lv.clone() compareResult = lv.clone() self.curBasicBlock.append(ir.LoadConstant(constZero.reg,ir.ConstantI32(0))) self.curBasicBlock.append(ir.Binop('!=',compareResult.reg,lv.reg,constZero.reg)) ifZero = basicblock.BasicBlock() ifNotZero = basicblock.BasicBlock() next = basicblock.BasicBlock() self.curBasicBlock.append(ir.Branch(compareResult.reg,ifNotZero,ifZero)) if node.op == '&&': shortCircuit = ifZero other = ifNotZero shortCircuitResult = 0 else: shortCircuit = ifNotZero other = ifZero shortCircuitResult = 1 self.curBasicBlock = shortCircuit self.curBasicBlock.append(ir.LoadConstant(result1.reg,ir.ConstantI32(shortCircuitResult))) if self.curBasicBlock.unsafeEnding(): self.curBasicBlock.append(ir.Jmp(next)) self.curBasicBlock = other rv = self.inFunctionDispatch(node.right) self.assertNonVoid(rv) if rv.lval: rv = self.genDeref(rv) #create some new virtual registers constZero = lv.clone() self.curBasicBlock.append(ir.LoadConstant(constZero.reg,ir.ConstantI32(0))) self.curBasicBlock.append(ir.Binop('!=',result2.reg,rv.reg,constZero.reg)) result2Reaching = self.curBasicBlock if self.curBasicBlock.unsafeEnding(): self.curBasicBlock.append(ir.Jmp(next)) self.curBasicBlock = next self.curBasicBlock.append(ir.Phi(result3.reg,[(result2.reg,result2Reaching),(result1.reg,shortCircuit)])) return result3 else: # a normal binop rv = self.inFunctionDispatch(node.right) self.assertNonVoid(lv) self.assertNonVoid(rv) return operatorgen.genBinop(self.curBasicBlock,node.op,lv,rv)