def __generate_alias(self, process, name, file, int_retval=False): new_name = "emg_{}".format(name) code = [ "{}();".format("return {}".format(name) if int_retval else name) ] # Add definition func = Function(new_name, "{}(void)".format("int {}".format(new_name) if int_retval else "void {}".format(new_name))) func.body = code process.add_definition(file, name, func.define()) process.add_declaration('environment model', name, 'extern {} {}(void);\n'.format("int" if int_retval else "void", new_name)) return new_name
def __generate_calls(self, functions_collection): def indented_line(t, s): return (t * "\t") + s # Generate process ep = Process("main") ep._category = 'generic' ep.comment = "Call exported functions." ep.pretty_id = 'zephyr/generic' ep.process = '' caller_func = Function("ldv_zephr", "void a(void)") # Generate actions for all sequence expressions = [] identifier = 0 for func in functions_collection: for obj in functions_collection[func]: self.logger.info("Call function {!r} from {!r}".format( func, obj.definition_file)) expr = self.__generate_call(ep, func, obj, identifier) expressions.append(expr) # Generate process description tab = 0 cnt = 0 for expr in expressions: caller_func.body.append(indented_line(tab, "{}".format(expr))) cnt += 1 ep.add_condition( 'function_calls', [], ["{}();".format(caller_func.name)], 'Call all initialization functions in asc order of level.') ep.process = "<function_calls>" ep.add_definition("environment model", caller_func.name, caller_func.define() + ["\n"]) return ep
def __generate_call(self, process, func_name, func_obj, identifier): """ Generate a C code to call a particular function. :param process: Process object to add definitions and declarations. :param func_name: Function name. :param func_obj: Function object. :param identifier: Numerical identifier. :return: List of C statements """ # Add declaration of caller caller_func = Function("emg_{}_caller_{}".format(func_name, identifier), "void a(void)") process.add_declaration("environment model", caller_func.name, caller_func.declare(True)[0]) expression = "" body = [] initializations = [] # Check retval and cast to void call if func_obj.declaration.return_value and func_obj.declaration.return_value != 'void': expression += "(void) " # Get arguments and allocate memory for them args = [] free_args = [] for index, arg in enumerate(func_obj.declaration.parameters): if not isinstance(arg, str): argvar = Variable("emg_arg_{}".format(index), arg) body.append(argvar.declare(scope={func_obj.definition_file}) + ";") args.append(argvar.name) if isinstance(arg, Pointer): elements = self.conf.get("initialize strings as null terminated") if elements and str(arg) == 'char **': if isinstance(elements, int) or elements.isnumeric(): elements = int(elements) else: elements = 'ldv_undef_int()' argvar_len = Variable(argvar.name + '_len', 'int') # Define explicitly number of arguments, since undef value is too difficult sometimes initializations.append("int {} = {};".format(argvar_len.name, elements)) initializations.append("{} = (char **) ldv_xmalloc({} * sizeof(char *));". format(argvar.name, argvar_len.name)) # Initialize all elements but the last one initializations.append("for (int i = 0; i < {} - 1; i++)".format(argvar_len.name)) # Some undefined data initializations.append("\t{}[i] = (char *) external_allocated_data();".format(argvar.name)) # The last element is a string initializations.append("{}[{}] = (char * ) 0;".format(argvar.name, elements - 1)) free_args.append(argvar.name) elif self.conf.get("allocate external", True): value = "external_allocated_data();" initializations.append("{} = {}".format(argvar.name, value)) else: if self.conf.get("allocate with sizeof", True): apt = arg.points.to_string('', typedef='complex_and_params') value = "ldv_xmalloc(sizeof({}));".\ format(apt if apt != 'void' else apt + '*') else: value = "ldv_xmalloc_unknown_size(0);" free_args.append(argvar.name) initializations.append("{} = {}".format(argvar.name, value)) # Generate call expression += "{}({});".format(func_name, ", ".join(args)) # Generate function body body += initializations + [expression] # Free memory for arg in free_args: body.append("ldv_free({});".format(arg)) caller_func.body = body # Add definition of caller process.add_definition(func_obj.definition_file, caller_func.name, caller_func.define() + ["\n"]) # Return call expression return "{}();".format(caller_func.name)
def __generate_insmod_process(self, source, inits, exits, kernel_initializations): self.logger.info( "Generate artificial process description to call Init and Exit module functions 'insmod'" ) ep = Process("insmod") ep.comment = "Initialize or exit module." ep.self_parallelism = False # Add subprocesses finally process = '' for i, pair in enumerate(inits): process += "<{0}>.(<init_failed_{1}>".format(pair[1], i) for j, pair2 in enumerate(exits[::-1]): if pair2[0] == pair[0]: break j = 1 for _, exit_name in exits[:j - 1:-1]: process += ".<{}>".format(exit_name) process += "|<init_success_{}>.".format(i) for _, exit_name in exits: process += "<{}>.".format(exit_name) # Remove the last dot process = process[:-1] process += ")" * len(inits) if kernel_initializations and inits: process += "<kernel_initialization>." \ "(<kerninit_success> | <kerninit_failed>.(" + process + "))" elif kernel_initializations and not inits: process += "<kernel_initialization>.(<kernel_initialization_success> | <kernel_initialization_fail>)" elif not inits and not kernel_initializations: raise NotImplementedError( "There is no both kernel initialization functions and module initialization " "functions") # This populates all actions parse_process(ep, process) ep.actions.populate_with_empty_descriptions() if len(kernel_initializations) > 0: body = ["int ret;"] label_name = 'emg_kernel_initialization_exit' # Generate kernel initializations for name, calls in kernel_initializations: for filename, func_name in calls: func = source.get_source_function(func_name, filename) if func: retval = not func.declaration.return_value == 'void' else: raise RuntimeError( "Cannot resolve function {!r} in file {!r}".format( name, filename)) new_name = self.__generate_alias(ep, func_name, filename, retval) statements = [] if retval: statements.extend([ "ret = {}();".format(new_name), "ret = ldv_post_init(ret);", "if (ret)", "\tgoto {};".format(label_name) ]) else: statements.append("{}();".format(new_name)) body.extend(statements) body.extend(["{}:".format(label_name), "return ret;"]) func = Function('emg_kernel_init', 'int emg_kernel_init(void)') func.body = body addon = func.define() ep.add_definition('environment model', 'emg_kernel_init', addon) ki_subprocess = ep.actions['kernel initialization'] ki_subprocess.statements = ["%ret% = emg_kernel_init();"] ki_subprocess.comment = 'Kernel initialization stage.' ki_subprocess.trace_relevant = True ki_success = ep.actions['ki_success'] ki_success.condition = ["%ret% == 0"] ki_success.comment = "Kernel initialization is successful." ki_failed = ep.actions['kerninit_failed'] ki_failed.condition = ["%ret% != 0"] ki_failed.comment = "Kernel initialization is unsuccessful." if len(inits) > 0: # Generate init subprocess for filename, init_name in inits: self.logger.debug("Found init function {!r}".format(init_name)) new_name = self.__generate_alias(ep, init_name, filename, True) init_subprocess = ep.actions[init_name] init_subprocess.comment = 'Initialize the module after insmod with {!r} function.'.format( init_name) init_subprocess.statements = [ "%ret% = {}();".format(new_name), "%ret% = ldv_post_init(%ret%);" ] init_subprocess.trace_relevant = True # Add ret label ep.add_label('ret', import_declaration("int label")) # Generate exit subprocess if len(exits) == 0: self.logger.debug("There is no exit function found") else: for filename, exit_name in exits: self.logger.debug("Found exit function {!r}".format(exit_name)) new_name = self.__generate_alias(ep, exit_name, filename, False) exit_subprocess = ep.actions[exit_name] exit_subprocess.comment = 'Exit the module before its unloading with {!r} function.'.format( exit_name) exit_subprocess.statements = ["{}();".format(new_name)] exit_subprocess.trace_relevant = True # Generate successful conditions for action in (a for a in ep.actions.filter(include={Block}) if str(a).startswith('init_success')): action.condition = ["%ret% == 0"] action.comment = "Module has been initialized." # Generate else branch for action in (a for a in ep.actions.filter(include={Block}) if str(a).startswith('init_failed')): action.condition = ["%ret% != 0"] action.comment = "Failed to initialize the module." return ep