[et] first draft

This commit is contained in:
Alexis Pereda 2019-07-02 17:21:34 +02:00
parent 12991f04e1
commit e99b4bdfb2
2 changed files with 89 additions and 0 deletions

View File

@ -13,3 +13,44 @@ make
``` ```
then run any example binary, located inside the `build/examples/` directory. then run any example binary, located inside the `build/examples/` directory.
## Remarks
### Assembler code
Some examples are meant to show the assembler code they generate.
To see that, one can use for example https://godbolt.org/ or GDB.
With GDB:
```bash
gdb -q -ex 'disassemble main' -ex q "${program_to_execute}"
```
Important note:
if using `cmake` to produce the Makefile, you must call it with at least:
```bash
cmake -DCMAKE_BUILD_TYPE=Release ..
```
or the examples will be compiled without the optimization level 2.
### use of `volatile`
When a value is required to show something, it is necessary to prevent the compiler to
optimize out this value. To achieve this, one can read the value from a file, for example,
but it will generate more assembler code.
Another solution is the `volatile` type modifier that forbids optimization like caching or
other optimizations like:
```cpp
int main() {
int volatile v0 = 5, v1 = 7;
return v0 + v1;
}
```
Without `volatile`, the addition is done by the compiler and `main` returns directly `12`.
With `volatile`, the generated assembler code will contain an `add` instruction, even with `-O2`.
### `std::printf` instead of `std::cout`
C++ iostreams cause lots of assembler code, for that reason, when an example is expected to be
possibly used by looking at its generated assembler code, iostreams are avoided and replaced by
`printf`.

View File

@ -0,0 +1,48 @@
#include <cstdio>
struct Add {
template<typename T>
static auto eval(T lhs, T rhs) {
return lhs + rhs;
}
};
struct Mul {
template<typename T>
static auto eval(T lhs, T rhs) {
return lhs * rhs;
}
};
template<typename T>
class Value {
T _value;
public:
Value(T value): _value(value) {}
auto eval() const { return _value; }
};
template<typename Op, typename LHS, typename RHS>
struct BinExpr {
LHS lhs;
RHS rhs;
auto eval() const {
return Op::eval(lhs.eval(), rhs.eval());
}
};
int main() {
using SubExpr = BinExpr<Mul, Value<int>, Value<int>>;
using MyExpr = BinExpr<Add, Value<int>, SubExpr>;
int volatile v0 = 3, v1 = 5, v2 = 7;
int result;
MyExpr expr{{v0}, {{v1}, {v2}}};
result = expr.eval();
std::printf("%d\n", result);
}