コード例 #1
0
ファイル: irgen.py プロジェクト: andrewchambers/pycc
 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
コード例 #2
0
ファイル: irgen.py プロジェクト: andrewchambers/pycc
 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
コード例 #3
0
ファイル: irgen.py プロジェクト: andrewchambers/pycc
 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)