The EmitC dialect allows to convert operations from other MLIR dialects to EmitC
ops. Those can be translated to C/C++ via the Cpp emitter.

The following convention is followed:

*   If template arguments are passed to an `emitc.call` operation, C++ is
    generated.
*   If tensors are used, C++ is generated.
*   If multiple return values are used within in a functions or an `emitc.call`
    operation, C++11 is required.
*   If floating-point type template arguments are passed to an `emitc.call`
    operation, C++20 is required.
*   Else the generated code is compatible with C99.

These restrictions are neither inherent to the EmitC dialect itself nor to the
Cpp emitter and therefore need to be considered while implementing conversions.

After the conversion, C/C++ code can be emitted with `mlir-translate`. The tool
supports translating MLIR to C/C++ by passing `-mlir-to-cpp`. Furthermore, code
with variables declared at top can be generated by passing the additional
argument `-declare-variables-at-top`.

Besides operations part of the EmitC dialect, the Cpp targets supports
translating the following operations:

*   'std' Dialect
    *   `std.br`
    *   `std.call`
    *   `std.cond_br`
    *   `std.constant`
    *   `std.return`
*   'scf' Dialect
    *   `scf.for`
    *   `scf.if`
    *   `scf.yield`
*   'arith' Dialect
    *   'arith.constant'
