[et] first draft
This commit is contained in:
parent
12991f04e1
commit
e99b4bdfb2
41
README.md
41
README.md
@ -13,3 +13,44 @@ make
|
||||
```
|
||||
|
||||
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`.
|
||||
|
48
examples/et/1_first_draft.cpp
Normal file
48
examples/et/1_first_draft.cpp
Normal 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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user