def _add_additional_preconditions(self) -> None: """Add preconditions about current thread and caller measures.""" preconditions = [] if not obligation_config.disable_all: cthread_var = self._obligation_info.current_thread_var cthread = sil.RefVar(cthread_var) preconditions.append(cthread != None) position = self._position if (self._is_body_native_silver() and not obligation_config.disable_termination_check): # Add obligations described in interface_dict. assert self._python_method.interface for obligation in self._obligation_manager.obligations: preconditions.extend( obligation.generate_axiomatized_preconditions( self._obligation_info, self._python_method.interface_dict)) func_node = self.get_function_node() position = self._translator.to_position( func_node, self._ctx, rules=rules.OBLIGATION_CALL_LEAK_CHECK_FAIL) translated = [ precondition.translate(self._translator, self._ctx, position, self._info) for precondition in preconditions ] if not obligation_config.disable_all: translated.append( self._translator.var_type_check(cthread_var.sil_name, cthread_var.type, self._position, self._ctx)) self._obligation_method.prepend_precondition(translated) self._obligation_method.append_preconditions( self._obligation_info.get_additional_preconditions())
def generate_axiomatized_preconditions( self, obligation_info: 'PythonMethodObligationInfo', interface_dict: Dict[str, Any]) -> List[sil.BoolExpression]: """Add ``MustTerminate(1)`` to axiomatic method precondition.""" if self.is_interface_method_terminating(interface_dict): cthread = sil.RefVar(obligation_info.current_thread_var) check = obligation_info.caller_measure_map.check( cthread, sil.RawIntExpression(1)) return [check] else: return []
def _create_level_op( self, expr: sil.PermExpression, residue_level_var: sil.PermExpression, ctx: Context, oper: Union[operator.le, operator.lt]) -> sil.BoolExpression: obligation = self._obligation_manager.must_release_obligation fields = obligation.create_fields_untranslated() var = ctx.current_function.create_variable( '_r', ctx.module.global_module.classes['object'], self.translator, local=False) op = oper(self.create_level_call(sil.RefVar(var)), expr) for_perms = [sil.ForPerm(var.sil_name, f, op) for f in fields] return sil.BigAnd(for_perms + [oper(residue_level_var, expr)])
def _create_level_below(self, expr: sil.PermExpression, ctx: Context) -> sil.BoolExpression: residue_level_var = sil.PermVar( ctx.actual_function.obligation_info.residue_level) obligation = self._obligation_manager.must_release_obligation fields = obligation.create_fields_untranslated() var = ctx.current_function.create_variable( '_r', ctx.module.global_module.classes[OBJECT_TYPE], self._translator.translator, local=False) op = operator.lt(self.create_level_call(sil.RefVar(var)), expr) for_perms = [sil.ForPerm(var.sil_name, f, op) for f in fields] return sil.BigAnd(for_perms + [operator.lt(residue_level_var, expr)])
def _add_caller_leak_check(self) -> None: """Add a leak check. Check that if callee is not terminating, caller has no obligations. """ if obligation_config.disable_call_context_leak_check: return # MustTerminate leak check. must_terminate = self._obligation_manager.must_terminate_obligation cthread = self._obligation_info.current_thread_var predicate = must_terminate.create_predicate_access(cthread) termination_leak_check = sil.CurrentPerm(predicate) == sil.NoPerm() # Other obligations leak check. reference_name = self._python_method.get_fresh_name('_r') leak_check = self._obligation_manager.create_leak_check(reference_name) if self._python_method.interface: if must_terminate.is_interface_method_terminating( self._python_method.interface_dict): exhale = self._obligation_info.caller_measure_map.check( sil.RefVar(self._obligation_info.current_thread_var), sil.RawIntExpression(1)) else: exhale = sil.BigAnd([termination_leak_check, leak_check]) else: # Termination condition. tcond = self._obligation_info.create_termination_check(False) # Combination. exhale = sil.BigOr( [tcond, sil.BigAnd([termination_leak_check, leak_check])]) check = sil.InhaleExhale(sil.TrueLit(), exhale) # Translate to Silver. node = self.get_function_node() position = self._translator.to_position( node, self._ctx, rules=rules.OBLIGATION_CALL_LEAK_CHECK_FAIL) info = self._translator.to_info(["Caller side leak check"], self._ctx) precondition = check.translate(self._translator, self._ctx, position, info) self._obligation_method.append_preconditions([precondition])
def construct_loop_condition(self) -> sil.BoolExpression: """Construct loop condition.""" if isinstance(self.node, ast.While): return sil.PythonBoolExpression(self.node.test) else: return sil.RefVar(self.iteration_err_var) == None # noqa: E711
def _check_must_terminate_measure_decrease( self, measure: sil.IntExpression) -> sil.BoolExpression: return self.loop_measure_map.check(sil.RefVar(self.current_thread_var), measure)
def get_target(self) -> sil.RefExpression: return sil.RefVar(self._target)
def _create_predicate_access(cthread: PythonVar) -> sil.PredicateAccess: """Create a predicate access expression.""" return sil.PredicateAccess(_PREDICATE_NAME, sil.RefVar(cthread))
def _translate_level(self, node: ast.Call) -> sil.PermExpression: """Translate a call to ``Level``.""" assert len(node.args) == 1 arg = sil.RefVar(node.args[0]) return self.create_level_call(arg)