Beispiel #1
0
    def compose_entry_point(self, given_body):
        """
        Generate an entry point function for the environment model.

        :param given_body: Body of the main function provided by a translator.
        :return: List of C statements of the generated function body.
        """
        ep = Function(self.entry_name, "int {}(void)".format(self.entry_name))
        ep.definition_file = self.entry_file
        body = ['/* EMG_ACTION {' + '"thread": 1, "type": "CONTROL_FUNCTION_BEGIN", "comment": "Entry point \'{0}\'", '
                '"function": "{0}"'.format(self.entry_name) + '} */']

        # Init external allocated pointers
        cnt = 0
        functions = []
        if len(self.__external_allocated.keys()) > 0:
            for file, ext_vars in ((f, v) for f, v in self.__external_allocated.items() if v):
                func = Function('emg_allocate_external_{}'.format(cnt),
                                "void emg_allocate_external_{}(void)".format(cnt))
                func.declaration_files.add(file)
                func.definition_file = file

                init = ["{} = {}();".format(var.name, 'external_allocated_data') for var in ext_vars]
                func.body = init

                self.add_function_definition(func)
                self.add_function_declaration(self.entry_file, func, extern=True)
                functions.append(func)
                cnt += 1

            gl_init = Function('emg_initialize_external_data', 'void emg_initialize_external_data(void)')
            gl_init.declaration_files.add(self.entry_file)
            gl_init.definition_file = self.entry_file
            init_body = ['{}();'.format(func.name) for func in functions]
            gl_init.body = init_body
            self.add_function_definition(gl_init)
            body += [
                '/* Initialize external data */',
                'emg_initialize_external_data();'
            ]

        if self._conf.get("initialize requirements", True):
            body.append('ldv_initialize();')

        comment_data = {'action': 'scenarios'}
        body += [model_comment('ACTION_BEGIN', 'Begin Environment model scenarios', comment_data)] + given_body + \
                [model_comment('ACTION_END', other=comment_data)]

        if self._conf.get("check final state", True):
            body.append('ldv_check_final_state();')

        body += ['return 0;',
                 '/* EMG_ACTION {' +
                 '"comment": "Exit entry point \'{0}\'", "type": "CONTROL_FUNCTION_END", "function": "{0}"'.
                 format(self.entry_name) + '} */']

        ep.body = body
        self.add_function_definition(ep)

        return body
Beispiel #2
0
    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
Beispiel #3
0
    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)
Beispiel #4
0
    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