From 737371dca6a6a3c18e2f185f8ce893639dd03247 Mon Sep 17 00:00:00 2001
From: Per <Per Lindgren>
Date: Mon, 8 Jan 2018 16:28:06 +0100
Subject: [PATCH] bare0

---
 README.md         | 130 +++++++++++++++++++---------------------------
 examples/bare0.rs |   2 +-
 2 files changed, 53 insertions(+), 79 deletions(-)

diff --git a/README.md b/README.md
index 9d12913..d1bb158 100644
--- a/README.md
+++ b/README.md
@@ -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`.
 
@@ -348,92 +348,66 @@ fn main() {
         x += 1;
  80004a2:	9802      	ldr	r0, [sp, #8]
  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]
+ ...
+ ````
+
+We see that the compiler has genereted quite some code for the small `main` function.
+
+We can compile the `bare0` application in -- release mode instead.
+
+``` shell
+> 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;
- 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
+ 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 {
- 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
- ````
+        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
+```
 
-We see that the compiler has genereted quite some code for the small `main` function.
+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.
 
-We can compile the `bare0` application in -- release mode instead.
 
-``` shell
->  xargo build --release  --example bare0
-```
 
 
 # License
diff --git a/examples/bare0.rs b/examples/bare0.rs
index fdb45a2..d099aba 100644
--- a/examples/bare0.rs
+++ b/examples/bare0.rs
@@ -21,7 +21,7 @@ fn main() {
     loop {
         x += 1;
         unsafe {
-            X += 1;
+            //X += 1;
             Y = X;
             assert!(x == X && X == Y);
         }
-- 
GitLab