
# Developing a new backend

The FIR (Faust Imperative Representation) is generated by converting signals to FIR instructions, defined in `instructions.hh` and `instructions.cpp` files. The conversion is done in `InstructionsCompiler` for the *-scalar* mode and `DAGInstructionsCompiler` for *-vec*, *-omp*, *-sch* Direct Acyclic Graph (DAG) based generators.

Backends are implemented in sub-folders in the *generator* folder. They can be added in the compiler (either the `faust` executable or the `libfaust` library) using a compilation time activation model.

## Adding the backend code

A backend typically subclasses the `CodeContainer` class which will contain the FIR generated code for the different methods to generate (`init`, `buildUserInterface`, `compute`,etc.). For the template backend, the code in defined in the `template_code_container.hh`and `template_code_container.cpp` files:
- the `TemplateCodeContainer` is  the base class for all backends code generation options (*-scalar*, *-vec*, *-omp*, *-sch*)
- the `TemplateScalarCodeContainer` implements the container used in *-scalar*
- the `TemplateVectorCodeContainer` implements the container used in *-vec*
- for options like *-omp*, *-sch*, the corresponding `TemplateOpenMPCodeContainer` and `TemplateWorkStealingCodeContainer` classes would have to be implemented and activated
    
A `TemplateInstVisitor` visitor pattern implemented in `template_instructions.hh` is used to traverse the FIR code to generate the code. It actually shows an example of a [textual backend](#textual-backend), and is written by subclassing the `TextInstVisitor` base class for textual visitors. Note that this template code is given as an example and will have to be adapted to real use-cases. Looking at already written ones like the C or Julia backends can help.

The `TemplateCodeContainer` base class implements in particular:
- the `produceClass` method wich is responsible to generate the entire piece of code
- the `produceInternal` method possibly used for sub containers
- the `produceMetadata` method to generate the global metadata
- the waveforms are inlined in the DSP structure (see `TemplateInitFieldsVisitor`usage in the `TemplateCodeContainer::produceClass` method, in the `// Fields` section)

The `TemplateScalarCodeContainer` class implements the `compute` method to generate the specific version of DSP computation in *-scalar* mode. The `TemplateVectorCodeContainer` class implements the `compute` method to generate the specific version of DSP computation in *-vec* mode. 

### Inlining subcontainers

The `rdtable` and `rwtable` primitives are treated as *sub containers* which possibly generate separated pieces of code (like additional C++ classes in the C++ backend, or LLVM modules in the LLVM backend). It may be easier to have the sub containers *be inlined* in the main module. This can be done at the appropriate locations using this kind of code:

```c++
// Rename 'sig' in 'dsp', remove 'dsp' allocation, 
// inline subcontainers 'instanceInit' and 'fill' function call
inlineSubcontainersFunCalls(fInitInstructions)->accept(gGlobal->gTemplateVisitor);
``` 

Look at the `TemplateCodeContainer::produceClass()` method for a precise way of using it.

## Compiling the backend

Faust compilation and installation is based on CMake, you should look at the [Faust wiki pages](https://github.com/grame-cncm/faust/wiki). 

A set of cmake files have to be adapted for the new backed to be properly commpiled and activated:

- targets included into your projects are specified using a configuration file located in the targets folder
- the [backends selection](https://github.com/grame-cncm/faust/wiki/backends#selecting-your-backends) is described using `backends` files located in the [backends](https://github.com/grame-cncm/faust/tree/master-dev/build/backends) folder. **These files will have to be adapted to activate the new backend**
- the backend build flag (like `TEMPLATE_BUILD` in this case) has to be added in the [scan_backends](https://github.com/grame-cncm/faust/blob/master-dev/build/misc/llvm.cmake#L14) function defined in the [llvm.cmake](https://github.com/grame-cncm/faust/blob/master-dev/build/misc/llvm.cmake) file

The new backend may define some globals that have to be added in the `global` class defined in `global.hh`and `global.cpp` files. For instance the unique `TemplateInstVisitor` object is defined and allocated with the appropriate `#ifdef TEMPLATE_BUILD .... #endif` flags.

## Activating the backend

The new backend will have to be allocated and activated in the `libcode.cpp` file with the following kind of code:

In the header part of the file:

```c++
#ifdef TEMPLATE_BUILD
#include "template_code_container.hh"
#endif
```

In the `enumBackends` function:

```c++
#ifdef TEMPLATE_BUILD
    out << dspto << "Template" << endl;
#endif
```

With the following kind of code to create the backend:

```c++
static void compileTemplate(Tree signals, int numInputs, int numOutputs, ostream* out)
{
#ifdef TEMPLATE_BUILD
    // Backend configuration
    gGlobal->gAllowForeignFunction = true;
    gGlobal->gNeedManualPow        = false;
    gGlobal->gFAUSTFLOAT2Internal  = true;
    container = TemplateCodeContainer::createContainer(gGlobal->gClassName, numInputs, numOutputs, out);
    
    if (gGlobal->gVectorSwitch) {
        new_comp = new DAGInstructionsCompiler(container);
    } else {
        new_comp = new InstructionsCompiler(container);
    }
    
    if (gGlobal->gPrintXMLSwitch || gGlobal->gPrintDocSwitch) new_comp->setDescription(new Description());
    new_comp->compileMultiSignal(signals);
#else
    throw faustexception("ERROR : -lang temp not supported since Template backend is not built\n");
#endif
}
```

To be added in `generateCode` function with a new `temp` flag to be used in the `-lang` option (like `-lang temp` with this new template backend):

```c++
else if (gGlobal->gOutputLang == "temp") {
    compileTemplate(signals, numInputs, numOutputs, dst.get());
}
```

The `-lang` option in the `printHelp` documentation function has to be manually adapted.

## Textual backend

A textual backend will generate code in a C++ stream. It typically uses a subclass of `TextInstVisitor` to define its specific FIR traversing methods.

## Binary backend 

A binary backend will generate binary code using an tailor-made output, which can greaty depends of the use-case. Look at the LLVM backend which outputs LLVM IR code, and the WASM backend which outputs binary WebAssembly code.
