Split

Outline pieces of a function into their own functions. This transformation is useful, for example, to break a large, virtualized, function into smaller, less conspicuous, pieces. Four different splitting methods are supported. The order in which they are tried can affect the naturalness of the resulting code.

OptionArgumentsDescription
--Transform Split Outline pieces of a function
--SplitKinds top, block, deep, recursive, level, inside Comma-separated list specifying the order in which different split methods are attempted. Default=top,block,deep,recursive.
  • top = split the top-level list of statements into two functions funcname_split_1 and funcname_split_2.
  • block = split a basic block (list of assignment and call statements) into two functions.
  • deep = split out a nested control structure of at least height>2 into its own function funcname_split_1.
  • recursive = same as block, but calls to split functions are also allowed to be split out.
  • level = split out a statement at a level specified by --SplitLevel.
  • inside = split out a statement at the innermost nesting level.
--SplitCount INTSPEC How many times to attempt the split. Default=1.
--SplitName string If --SplitName=name is given, the split out functions will be named prefix_name_number, otherwise they will be named prefix_originalName_split_number. Default=none.
--SplitLevel INTSPEC Levels which could be split out when specifying --SplitKinds=level. Default=1.
--SplitLocalsAsFormals BOOLSPEC Pass local variables as formals to split out functions. Can cause functions to have many arguments which can be a problem for languages like WebAssembly that puts a limit on the number of function arguments. Default=true.
 

Examples

This command first tries to split function foo at most 100 times, then applies the block split transformation to the resulting outlined function. Note the use of a regular expression to specify the names of the functions that were generated in the first transformation:

tigress --Seed=0 \
   --Transform=split \
       --SplitKinds=deep,block,top \
       --SplitCount=100 \
       --Functions=foo \
   --Transform=Split \
       --SplitKinds=block \
       --SplitCount=100 \
       --Functions=/.\*foo_split.\*/ \
   --out=foo prog.c
 

Issues

  • For functions that have many locals, the number of formal parameters may explode. This is particularly an issue for WebAssembly, since compilers will put a limit on the number of formal parameters. --SplitLocalsAsFormals=false will instead just add one formal, a pointer to a struct that holds all the locals. This option still has a bug in it; you will know, since it causes a compile-time error.