def eval_operation(self, operation): tracer = self.llinterpreter.tracer if tracer: tracer.dump(str(operation)) ophandler = self.getoperationhandler(operation.opname) # XXX slighly unnice but an important safety check if operation.opname == 'direct_call': assert isinstance(operation.args[0], Constant) elif operation.opname == 'indirect_call': assert isinstance(operation.args[0], Variable) if getattr(ophandler, 'specialform', False): retval = ophandler(*operation.args) else: vals = [self.getval(x) for x in operation.args] if getattr(ophandler, 'need_result_type', False): vals.insert(0, operation.result.concretetype) try: retval = ophandler(*vals) except LLException as e: # safety check check that the operation is allowed to raise that # exception if operation.opname in lloperation.LL_OPERATIONS: canraise = lloperation.LL_OPERATIONS[operation.opname].canraise if Exception not in canraise: exc = self.llinterpreter.find_exception(e) for canraiseexc in canraise: if issubclass(exc, canraiseexc): break else: raise TypeError("the operation %s is not expected to raise %s" % (operation, exc)) # for exception-transformed graphs, store the LLException # into the exc_data used by this graph exc_data = self.llinterpreter.get_transformed_exc_data( self.graph) if exc_data: etype = e.args[0] evalue = e.args[1] exc_data.exc_type = etype exc_data.exc_value = evalue from rpython.translator import exceptiontransform retval = exceptiontransform.error_value( operation.result.concretetype) else: raise self.setvar(operation.result, retval) if tracer: if retval is None: tracer.dump('\n') else: tracer.dump(' ---> %r\n' % (retval,))
def eval_operation(self, operation): tracer = self.llinterpreter.tracer if tracer: tracer.dump(str(operation)) ophandler = self.getoperationhandler(operation.opname) # XXX slighly unnice but an important safety check if operation.opname == 'direct_call': assert isinstance(operation.args[0], Constant) elif operation.opname == 'indirect_call': assert isinstance(operation.args[0], Variable) if getattr(ophandler, 'specialform', False): retval = ophandler(*operation.args) else: vals = [self.getval(x) for x in operation.args] if getattr(ophandler, 'need_result_type', False): vals.insert(0, operation.result.concretetype) try: retval = ophandler(*vals) except LLException, e: # safety check check that the operation is allowed to raise that # exception if operation.opname in lloperation.LL_OPERATIONS: canraise = lloperation.LL_OPERATIONS[ operation.opname].canraise if Exception not in canraise: exc = self.llinterpreter.find_exception(e) for canraiseexc in canraise: if issubclass(exc, canraiseexc): break else: raise TypeError( "the operation %s is not expected to raise %s" % (operation, exc)) # for exception-transformed graphs, store the LLException # into the exc_data used by this graph exc_data = self.llinterpreter.get_transformed_exc_data( self.graph) if exc_data: etype = e.args[0] evalue = e.args[1] exc_data.exc_type = etype exc_data.exc_value = evalue from rpython.translator import exceptiontransform retval = exceptiontransform.error_value( operation.result.concretetype) else: raise
raise LLException(etype, evalue) resultvar, = block.getvariables() result = self.getval(resultvar) exc_data = self.llinterpreter.get_transformed_exc_data(self.graph) if exc_data: # re-raise the exception set by this graph, if any etype = exc_data.exc_type if etype: evalue = exc_data.exc_value if tracer: tracer.dump('raise') exc_data.exc_type = lltype.typeOf(etype)._defl() exc_data.exc_value = lltype.typeOf(evalue)._defl() from rpython.translator import exceptiontransform T = resultvar.concretetype errvalue = exceptiontransform.error_value(T) # check that the exc-transformed graph returns the error # value when it returns with an exception set assert result == errvalue raise LLException(etype, evalue) if tracer: tracer.dump('return') return None, result elif block.exitswitch is None: # single-exit block assert len(block.exits) == 1 link = block.exits[0] elif block.canraise: link = block.exits[0] if e: exdata = self.llinterpreter.typer.exceptiondata
def eval_block(self, block): """ return (nextblock, values) tuple. If nextblock is None, values is the concrete return value. """ self.curr_block = block e = None try: for i, op in enumerate(block.operations): self.curr_operation_index = i self.eval_operation(op) except LLException as e: if op is not block.raising_op: raise except RuntimeError as e: rstackovf.check_stack_overflow() # xxx fish fish fish for proper etype and evalue to use rtyper = self.llinterpreter.typer bk = rtyper.annotator.bookkeeper classdef = bk.getuniqueclassdef(rstackovf._StackOverflow) exdata = rtyper.exceptiondata evalue = exdata.get_standard_ll_exc_instance(rtyper, classdef) etype = exdata.fn_type_of_exc_inst(evalue) e = LLException(etype, evalue) if op is not block.raising_op: raise e # determine nextblock and/or return value if len(block.exits) == 0: # return block tracer = self.llinterpreter.tracer if len(block.inputargs) == 2: # exception if tracer: tracer.dump('raise') etypevar, evaluevar = block.getvariables() etype = self.getval(etypevar) evalue = self.getval(evaluevar) # watch out, these are _ptr's raise LLException(etype, evalue) resultvar, = block.getvariables() result = self.getval(resultvar) exc_data = self.llinterpreter.get_transformed_exc_data(self.graph) if exc_data: # re-raise the exception set by this graph, if any etype = exc_data.exc_type if etype: evalue = exc_data.exc_value if tracer: tracer.dump('raise') exc_data.exc_type = lltype.typeOf(etype)._defl() exc_data.exc_value = lltype.typeOf(evalue)._defl() from rpython.translator import exceptiontransform T = resultvar.concretetype errvalue = exceptiontransform.error_value(T) # check that the exc-transformed graph returns the error # value when it returns with an exception set assert result == errvalue raise LLException(etype, evalue) if tracer: tracer.dump('return') return None, result elif block.exitswitch is None: # single-exit block assert len(block.exits) == 1 link = block.exits[0] elif block.canraise: link = block.exits[0] if e: exdata = self.llinterpreter.typer.exceptiondata cls = e.args[0] inst = e.args[1] for link in block.exits[1:]: assert issubclass(link.exitcase, py.builtin.BaseException) if self.op_direct_call(exdata.fn_exception_match, cls, link.llexitcase): self.setifvar(link.last_exception, cls) self.setifvar(link.last_exc_value, inst) break else: # no handler found, pass on raise e else: llexitvalue = self.getval(block.exitswitch) if block.exits[-1].exitcase == "default": defaultexit = block.exits[-1] nondefaultexits = block.exits[:-1] assert defaultexit.llexitcase is None else: defaultexit = None nondefaultexits = block.exits for link in nondefaultexits: if link.llexitcase == llexitvalue: break # found -- the result is in 'link' else: if defaultexit is None: raise ValueError("exit case %r not found in the exit links " "of %r" % (llexitvalue, block)) else: link = defaultexit return link.target, [self.getval(x) for x in link.args]