Example #1
0
 def _format_indirect_call_multitarget(self, branch: blocks.Branch,
                                       uuid: int) -> str:
     paths = branch.next_target_sequence()
     max_index = len(paths)
     paths_array_name = f'paths_{uuid}'
     paths_array = self._create_target_sequence_array(
         paths, paths_array_name)
     func_array = self._create_call_target_array(branch.get_targets(),
                                                 f'array_{uuid}')
     result = (
         f'static int index_{uuid} = 0;\n'
         f'{paths_array}'
         f'{func_array}'
         f'void (*f_{uuid})(void) = '
         f'array_{uuid}[{paths_array_name}[index_{uuid}++ % {max_index}]];\n'
         f'f_{uuid}();\n')
     return result
Example #2
0
 def _format_branch_indirect(self, branch: blocks.Branch) -> str:
     target = branch.next_valid_target()
     label = self.format_code_block_label(self.code_blocks[target])
     branch_id = id(branch)
     fake_label = f'label{branch_id}'
     result = (f'{fake_label}:;\n'
               'int label_target = 0;\nvoid* array[] = {'
               f'&&{label}'
               f', &&{fake_label}'
               '};\n'
               'goto *(array[label_target]);\n')
     return result
Example #3
0
 def _build_switch_cases(self, branch: blocks.Branch) -> str:
     result = ''
     for i in range(len(branch.targets)):
         target = branch.get_target_from_index(i)
         new_string = f'case {i}:\n'
         if target is None:
             # Fallthrough branch
             new_string = f'{new_string}\tbreak;\n'
         else:
             label = self.format_code_block_label(self.code_blocks[target])
             new_string = f'{new_string}\tgoto {label};\n'
         result += new_string
     return result
Example #4
0
 def _format_branch_conditional_direct(self, branch: blocks.Branch) -> str:
     paths = branch.next_target_sequence()
     max_index = len(paths)
     branch_id = id(branch)
     paths_array_name = f'paths_{branch_id}'
     paths_array = self._create_target_sequence_array(
         paths, paths_array_name)
     switch_cases = self._build_switch_cases(branch)
     result = (
         f'static int index_{branch_id} = 0;\n'
         f'{paths_array}'
         f'switch ({paths_array_name}[index_{branch_id}++ % {max_index}]) '
         '{\n'
         f'{switch_cases}'
         '}\n')
     return result
Example #5
0
    def _format_branch_indirect_call(self,
                                     branch: blocks.Branch,
                                     uuid: int = None) -> str:
        """Format an indirect call.

        Args:
            branch: blocks.Branch instance. Must have branch_type of
              INDIRECT_CALL.
            uuid: Unique suffix to use for local variables. Used to
              differentiate multiple branches in a single function and to avoid
              any overlapping variables provided in user defined instructions.
              Leaving unspecified will let the program decide a unique suffix.

        Returns:
            A str representing an indirect call in C.
        """
        if uuid is None:
            uuid = id(branch)
        if len(branch.get_targets()) == 1:
            return self._format_indirect_call_singletarget(branch, uuid)
        return self._format_indirect_call_multitarget(branch, uuid)
Example #6
0
 def _format_branch_direct(self, branch: blocks.Branch) -> str:
     target = branch.next_valid_target()
     label = self.format_code_block_label(self.code_blocks[target])
     return f'goto {label};\n'
Example #7
0
 def _format_branch_direct_call(self, branch: blocks.Branch) -> str:
     target = branch.next_valid_target()
     string = self.function_call_signature_for(target)
     return f'{string}();\n'
Example #8
0
 def _format_indirect_call_singletarget(self, branch: blocks.Branch,
                                        uuid: int) -> str:
     target = branch.next_valid_target()
     sig = self.function_call_signature_for(target)
     return (f'void (*frontend_{uuid})(void) = {sig};\n'
             f'frontend_{uuid}();\n')