# ROSE Compiler Framework/Inliner

The ROSE Inliner inlines functions at function callsites.

## Background

An inline function is one for which the compiler copies the code from the function definition directly into the code of the calling function rather than creating a separate set of instructions in memory. Instead of transferring control to and from the function code segment, a modified copy of the function body may be substituted directly for the function call. In this way, the performance overhead of a function call is avoided. The inline specifier is only a suggestion to the compiler that an inline expansion can be performed; the compiler is free to ignore the suggestion.

## User Instructions

You must enable EDG 5.0 to inline C++11 code
* --enable-edg_version=5.0

### install the tool

configure and build ROSE as instructed at https://github.com/rose-compiler/rose/wiki
inlineEverything -c [options] input.c

### Usage

This is a program transformation tool to inline function calls in your C/C++ or Fortran code.
Usage: inlineEverything -c [options] input.c
The optional options include:
* -skip-postprocessing: Skip postprocessing which cleanups code
* -process-headers: Process calls within header files
* -verbose: Printout debugging information
* -limit N: Inline up to N functions, then stop
* -main-only: Inline only functions reachable from main

## Source code

API and implementation:
* https://github.com/rose-compiler/rose/tree/develop/src/midend/programTransformation/astInlining
The tool's source code
* https://github.com/rose-compiler/rose/tree/develop/tests/nonsmoke/functional/roseTests/astInliningTests/inlineEverything.C
** command line processing is handled in this source file

## Algorithm
### Major steps

* eligibility check: skip things which cannot be inlined
* if a function call is used as an expression operand: e.g. a = func1 + func2;
** generate a temp variable to obtain the returned value: e.g. temp = func1;
** replace the function call expression with the temp variable. e.g. a = temp + temp;
** a slight optimization: if the function call is the only expression operand: e.g. a= func1. No temp variable is needed (a can be directly used without another temp variable serving as intermediate variable.)
* obtain the list of actual argument
* make a copy of the body of the function to be inlined
* rename labels in an inlined function definition. goto statements to them will be updated.
* in the function body
** create local variables , one per formal argument, initialize each with the actual argument
** build a paramMap: mapping formal arguments (SgInitializedName) to new local variables (SgVariableSymbol)
** this pointer is handled similarly: create a local variable , initialized with the caller's this pointer
** replace variable references in the body with actual arguments // ReplaceParameterUseVisitor(paramMap).traverse(funbody_copy, postorder);
** insert a label to indicate the end of the inlined function body // rose_inline_end__
Limitations of this algorithm is not very clean:
* It generates new local variables and a label.

### Eligibility check

What can be inlined
* a named function,
* static member function, or
* qualified name does not start with "::std:: " // skip std:: functions
* non-virtual non-static member function, // skip virtual functions, static member functions cannot access this->data (non-static data). That is why we check non-static for this ptr case.
* the function must be known (not through a function pointer or member function pointer). // empty function reference expression
* the body of the function must already be visible in the current AST. // skip functions with empty body

### postprocessing

inlineEverything.C has a clean up step to make the outlined code better
* cleanupInlinedCode(sageProject);
** remove unused labels: SageInterface::removeUnusedLabels(top);
** remove jumps to next statement: SageInterface::removeJumpsToNextStatement(top);
** simpleCopyAndConstantPropagation // In code with declarations such as "int foo = bar", where foo and bar are not modified, replace "foo" with "bar" and remove the declaration
** remove null statements: RemoveNullStatementsVisitor.traverse(top, postorder);
** move declaration to first use: MoveDeclarationsToFirstUseVisitor.traverse(top, postorder); e.g. int x__2 =7; w= x_2 +3; ==> w=7+3;
** doSubexpressionExpansionSmart // Replaces all uses of a variable by its initialing expression. Requires that initname has an assign initializer Replaces all uses of initname in initname's scope by copy of its initializer expression. Then removes initname.
* changeAllMembersToPublic(sageProject);
This step does lots of things and can easily trigger some bugs.
* Even wrose, the cleanup step operates on the entire AST, including C++ headers.

## Testing

Test directory with an example translator and test input files
* https://github.com/rose-compiler/rose/tree/develop/tests/nonsmoke/functional/roseTests/astInliningTests
By looking into Makefile.am, the example translator's source code will generate an executable named "inlineEverything" in your buildtree.

### translator: inlineEverything

This is the tool you can try to inline your sample code.
* inlineEverything
The same Makefile.am's make check rules contain sample command lines to use the tool.
To test one individual input file (such as template_functions.C), type
* make inlineEverything_template_functions.C.passed // TODO: udpate to new ways to trigger the tests

### Command line options

inlineEverything --help

### Correctness checking

make check only check if the number of inlined functions is the same as expected.

## examples

We use a set of increasingly more complex examples to explain the inlining algorithm used.
More example input and output files are available at:
* https://github.com/chunhualiao/inliner-demo

### function call as a single expression

An optimized transformation:
* not blindly generate a temp variable to capture the value of a function call.
* instead directly reuse the original declaration of the lhs variable inside the function body

### 3 operand operations

the code is normalized.

### multiple-level function calls
## Tutorial

Official documentation about how to call the inlining API is:
* Chapter 36 "Calling the Inliner of ROSE" tutorial: http://rosecompiler.org/ROSE_Tutorial/ROSE-Tutorial.pdf

## Troubleshooting

TEST inlineEverything ../../../../../../sourcetree/tests/nonsmoke/functional/roseTests/astInliningTests/template_functions.C [inlineEverything_template_functions.C.passed]
inlineEverything_template_functions.C [out]: Note: C++11 input files to ROSE are NOT supported using EDG 4.9 configuration with GNU compilers 4.9 and greater (configure ROSE using EDG 4.12)