Skip to content
Snippets Groups Projects
Commit 737371dc authored by Per's avatar Per
Browse files

bare0

parent 94ebfa71
No related branches found
No related tags found
No related merge requests found
...@@ -322,7 +322,7 @@ unsafe extern "C" fn reset_handler() -> ! { ...@@ -322,7 +322,7 @@ unsafe extern "C" fn reset_handler() -> ! {
``` ```
Here we see that the `reset_handler` intitates static heap variables (by 0 or value accordingly) before calling `main` (and puts the processor in sleep mode in case `main` returns). The user `main` has the symbol `bare0::main`, which is unknown to the `cortex-m-rt` library (defining the generic `reset_handler`). Hence the, `reset_handler` calls a compiler generated (trampoline) `main`, that in turn calls `bare0::main` (the user `main`). Here we see that the `reset_handler` intitates static heap variables (by 0 or value accordingly) before calling `main` (and puts the processor in sleep mode in case `main` returns). The user `main` has the symbol `bare0::main`, which is unknown to the `cortex-m-rt` library (defining the generic `reset_handler`). Hence the, `reset_handler` calls a compiler generated start item `main`, that in turn trampolines to `bare0::main` (the user `main`).
Finally, we can have a look at the user `main`. Finally, we can have a look at the user `main`.
...@@ -348,83 +348,7 @@ fn main() { ...@@ -348,83 +348,7 @@ fn main() {
x += 1; x += 1;
80004a2: 9802 ldr r0, [sp, #8] 80004a2: 9802 ldr r0, [sp, #8]
80004a4: 1c41 adds r1, r0, #1 80004a4: 1c41 adds r1, r0, #1
80004a6: 2201 movs r2, #1 ...
80004a8: 4281 cmp r1, r0
80004aa: bf28 it cs
80004ac: 2200 movcs r2, #0
80004ae: 2a00 cmp r2, #0
80004b0: 9101 str r1, [sp, #4]
80004b2: d146 bne.n 8000542 <bare0::main+0xb4>
80004b4: e7ff b.n 80004b6 <bare0::main+0x28>
80004b6: 9801 ldr r0, [sp, #4]
80004b8: 9002 str r0, [sp, #8]
unsafe {
X += 1;
80004ba: f240 0104 movw r1, #4
80004be: f2c2 0100 movt r1, #8192 ; 0x2000
80004c2: 6809 ldr r1, [r1, #0]
80004c4: 1c4a adds r2, r1, #1
80004c6: 2301 movs r3, #1
80004c8: 428a cmp r2, r1
80004ca: bf28 it cs
80004cc: 2300 movcs r3, #0
80004ce: 2b00 cmp r3, #0
80004d0: 9200 str r2, [sp, #0]
80004d2: d13d bne.n 8000550 <bare0::main+0xc2>
80004d4: e7ff b.n 80004d6 <bare0::main+0x48>
80004d6: f240 0004 movw r0, #4
80004da: f2c2 0000 movt r0, #8192 ; 0x2000
80004de: 9900 ldr r1, [sp, #0]
80004e0: 6001 str r1, [r0, #0]
Y = X;
80004e2: 6802 ldr r2, [r0, #0]
80004e4: f240 0300 movw r3, #0
80004e8: f2c2 0300 movt r3, #8192 ; 0x2000
80004ec: 601a str r2, [r3, #0]
assert!(x == X && X == Y);
80004ee: 9a02 ldr r2, [sp, #8]
80004f0: 6800 ldr r0, [r0, #0]
80004f2: 4282 cmp r2, r0
80004f4: d008 beq.n 8000508 <bare0::main+0x7a>
80004f6: e003 b.n 8000500 <bare0::main+0x72>
80004f8: 2001 movs r0, #1
80004fa: f807 0c01 strb.w r0, [r7, #-1]
80004fe: e010 b.n 8000522 <bare0::main+0x94>
8000500: 2000 movs r0, #0
8000502: f807 0c01 strb.w r0, [r7, #-1]
8000506: e00c b.n 8000522 <bare0::main+0x94>
8000508: f240 0004 movw r0, #4
800050c: f2c2 0000 movt r0, #8192 ; 0x2000
8000510: 6800 ldr r0, [r0, #0]
8000512: f240 0100 movw r1, #0
8000516: f2c2 0100 movt r1, #8192 ; 0x2000
800051a: 6809 ldr r1, [r1, #0]
800051c: 4288 cmp r0, r1
800051e: d0eb beq.n 80004f8 <bare0::main+0x6a>
8000520: e7ee b.n 8000500 <bare0::main+0x72>
8000522: f817 0c01 ldrb.w r0, [r7, #-1]
8000526: 43c0 mvns r0, r0
8000528: 07c0 lsls r0, r0, #31
800052a: 2800 cmp r0, #0
800052c: d008 beq.n 8000540 <bare0::main+0xb2>
800052e: e7ff b.n 8000530 <bare0::main+0xa2>
8000530: f640 10dc movw r0, #2524 ; 0x9dc
8000534: f6c0 0000 movt r0, #2048 ; 0x800
8000538: 6800 ldr r0, [r0, #0]
800053a: f000 f9c1 bl 80008c0 <core::panicking::panic>
800053e: defe udf #254 ; 0xfe
loop {
8000540: e7af b.n 80004a2 <bare0::main+0x14>
x += 1;
8000542: f640 106c movw r0, #2412 ; 0x96c
8000546: f6c0 0000 movt r0, #2048 ; 0x800
800054a: f000 f9b9 bl 80008c0 <core::panicking::panic>
800054e: defe udf #254 ; 0xfe
X += 1;
8000550: f640 1084 movw r0, #2436 ; 0x984
8000554: f6c0 0000 movt r0, #2048 ; 0x800
8000558: f000 f9b2 bl 80008c0 <core::panicking::panic>
800055c: defe udf #254 ; 0xfe
```` ````
We see that the compiler has genereted quite some code for the small `main` function. We see that the compiler has genereted quite some code for the small `main` function.
...@@ -433,8 +357,58 @@ We can compile the `bare0` application in -- release mode instead. ...@@ -433,8 +357,58 @@ We can compile the `bare0` application in -- release mode instead.
``` shell ``` shell
> xargo build --release --example bare0 > xargo build --release --example bare0
> arm-none-eabi-objdump -S -C target/thumbv7em-none-eabihf/release/examples/bare0 > objdump_release
``` ```
The resulting user main now looks like this.
``` rust
8000476 <_ZN5bare04main17h1039292c3948856dE.llvm.453292E5>:
loop {
x += 1;
unsafe {
X += 1;
Y = X;
assert!(x == X && X == Y);
8000476: e7fe b.n 8000476 <_ZN5bare04main17h1039292c3948856dE.llvm.453292E5>
```
The compiler has optimized away ALL your code!!! (`8000476: e7fe b.n 8000476` implements an infinite loop). Why you might ask, well it figures out that your the program has no *observable* effect (it will not output or change anything).
We can make a small change to the program (violating the assertion, by commenting out `X += 1;`. After compilation the oject dump of user main looks like this:
``` rust
08000476 <_ZN5bare04main17h1039292c3948856dE.llvm.E032C40E>:
static mut X: u32 = X_INIT;
static mut Y: u32 = 0;
#[inline(never)]
fn main() {
8000476: b580 push {r7, lr}
8000478: 466f mov r7, sp
loop {
x += 1;
unsafe {
//X += 1;
Y = X;
assert!(x == X && X == Y);
800047a: f240 5034 movw r0, #1332 ; 0x534
800047e: f6c0 0000 movt r0, #2048 ; 0x800
8000482: f000 f802 bl 800048a <core::panicking::panic>
8000486: defe udf #254 ; 0xfe
```
So the Rust compiler is able to figure out that the assertion will be violated and merely calls the `panic` routine. So be aware, the Rust compiler is extremely aggressive in optimizing your code. On a side note the semantics of integer additions is slightly different between `dev` (normal/non-optimized) and `--release` (optimized) builds. In `dev` build the arithmics are checked and overflows result in a `panic`, in `--release`, arithmetics are unchecked (for performance reasons), and oveflows wrap (under two's complement semantics). To avoid ambiguity, you may use methods defined in the std/core library:
- `wrapping_add`, `wrapping_sub`,returns the straight two’s complement result,
- `saturating_add`, `saturating_sub`, returns the largest/smallest value (as appropriate) of the type when overflow occurs,
- `overflowing_add`, `overflowing_sub`, returns the two’s complement result along with a boolean indicating if overflow occured, and
- `checked_add`, `checked_sub`, returns an `Option` that’s `None` when overflow occurs, and `Some(v)` elsewise.
Those methods never `panic`, but code might be verbose, e.g., expressing `x - y + z` under wrapping arithmetics equates to `x.wrapping_sub(y).wrapping_add(z)`. To this end you may choose to use the [Wrapping](https://doc.rust-lang.org/std/num/struct.Wrapping.html) type.
# License # License
......
...@@ -21,7 +21,7 @@ fn main() { ...@@ -21,7 +21,7 @@ fn main() {
loop { loop {
x += 1; x += 1;
unsafe { unsafe {
X += 1; //X += 1;
Y = X; Y = X;
assert!(x == X && X == Y); assert!(x == X && X == Y);
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment