www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.ldc - Cortex-M3 low level assert issue.

reply Jack Applegame <japplegame gmail.com> writes:
file test.d:

```
module test;

struct Foo {
     struct Bar {
         struct Baz {
         }
     }
}

void foo() {
     assert(0);
}
```

compile and dump:

```
$ ldc2 -c -mtriple=thumb-none-linux-eabi -mcpu=cortex-m3 test.d
$ arm-none-eabi-objdump -dhsS test.o > test.o.dump
```

LDC compiles `assert(0)` to `_d_assert(file, line)` call and puts 
file name (test.d) to section `.rodata.str1.1`:

```
Contents of section .rodata.str1.1:
  0000 74657374 2e466f6f 2e426172 00746573  test.Foo.Bar.tes
  0010 742e466f 6f007465 73742e64 00        t.Foo.test.d.
```

The problem is that this section also contains symbols 
`test.Foo.Bar` and `test.Foo`. I don't know why these symbols are 
needed, but they are definitely not used in the program. And 
because they are in the same section as `test.d`, this whole 
section goes into firmware.

In my real application, such useless data occupy an unacceptable 
amount of flash memory of the MCU. It would be nice to get rid of 
them.
May 01 2019
next sibling parent reply kinke <noone nowhere.com> writes:
On Wednesday, 1 May 2019 at 21:55:09 UTC, Jack Applegame wrote:
 In my real application, such useless data occupy an 
 unacceptable amount of flash memory of the MCU. It would be 
 nice to get rid of them.
That's what -betterC is for (omit ModuleInfos, TypeInfos etc.). If that's not an option, you can also hack your object.d and try to remove TypeInfo, ModuleInfo etc. We also have LDC-specific pragmas wrt. this.
May 02 2019
next sibling parent David Nadlinger <code klickverbot.at> writes:
On Thursday, 2 May 2019 at 09:24:00 UTC, kinke wrote:
 On Wednesday, 1 May 2019 at 21:55:09 UTC, Jack Applegame wrote:
 In my real application, such useless data occupy an 
 unacceptable amount of flash memory of the MCU. It would be 
 nice to get rid of them.
That's what -betterC is for (omit ModuleInfos, TypeInfos etc.). If that's not an option, you can also hack your object.d and try to remove TypeInfo, ModuleInfo etc. We also have LDC-specific pragmas wrt. this.
True, but shouldn't gc-sections (with llvm::TargetOptions::DataSections == true) take care of eliminating the unused strings? — David
May 02 2019
prev sibling parent reply Jack Applegame <japplegame gmail.com> writes:
On Thursday, 2 May 2019 at 09:24:00 UTC, kinke wrote:
 If that's not an option, you can also hack your object.d and 
 try to remove TypeInfo, ModuleInfo etc. We also have 
 LDC-specific pragmas wrt. this.
``` module test; pragma(LDC_no_moduleinfo); pragma(LDC_no_typeinfo) struct Foo { pragma(LDC_no_typeinfo) struct Bar { pragma(LDC_no_typeinfo) struct Baz { } } } void foo() { assert(0); } ``` Nothing changes.
May 04 2019
parent reply kinke <noone nowhere.com> writes:
On Saturday, 4 May 2019 at 14:05:00 UTC, Jack Applegame wrote:
 pragma(LDC_no_typeinfo)
 [...]
 Nothing changes.
Thanks for noting, that's a bug, tackled in https://github.com/ldc-developers/ldc/pull/3068.
May 04 2019
parent reply Jack Applegame <japplegame gmail.com> writes:
On Saturday, 4 May 2019 at 16:49:48 UTC, kinke wrote:
 Thanks for noting, that's a bug, tackled in 
 https://github.com/ldc-developers/ldc/pull/3068.
Thanks for fixing. And why `-data-sections` flag also doesn't change anything?
May 04 2019
parent reply kinke <noone nowhere.com> writes:
On Saturday, 4 May 2019 at 18:37:40 UTC, Jack Applegame wrote:
 And why `-data-sections` flag also doesn't change anything?
This seems to be the perfectly corresponding C++ question (string literals placed shared readonly section) with a nice answer: https://stackoverflow.com/questions/54996229/is-ffunction-sections-fdata-sections-and-gc-sections-not-working LDC emits these strings as private constants in LLVM IR.
May 04 2019
next sibling parent reply Jack Applegame <japplegame gmail.com> writes:
On Saturday, 4 May 2019 at 19:06:26 UTC, kinke wrote:
 On Saturday, 4 May 2019 at 18:37:40 UTC, Jack Applegame wrote:
 And why `-data-sections` flag also doesn't change anything?
This seems to be the perfectly corresponding C++ question (string literals placed shared readonly section) with a nice answer: https://stackoverflow.com/questions/54996229/is-ffunction-sections-fdata-sections-and-gc-sections-not-working LDC emits these strings as private constants in LLVM IR.
Thanks. Now I see.
May 05 2019
parent reply "David Nadlinger" <code klickverbot.at> writes:
On 5 May 2019, at 8:29, Jack Applegame via digitalmars-d-ldc wrote:
 On Saturday, 4 May 2019 at 19:06:26 UTC, kinke wrote:
 This seems to be the perfectly corresponding C++ question (string 
 literals placed shared readonly section) with a nice answer:
 https://stackoverflow.com/questions/54996229/is-ffunction-sections-fdata-sections-and-gc-sections-not-working

 LDC emits these strings as private constants in LLVM IR.
Thanks. Now I see.
Next question: How do we fix this? It seems like GCC might handle this by default: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=192 —David
May 05 2019
parent reply Mike Franklin <slavo5150 yahoo.com> writes:
On Sunday, 5 May 2019 at 15:40:58 UTC, David Nadlinger wrote:

 Next question: How do we fix this?

 It seems like GCC might handle this by default: 
 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=192

  —David
Iain fixed a similar issue a few years ago. I'm not sure if it's related or not: See the last comment here: https://issues.dlang.org/show_bug.cgi?id=14758 Mike
May 05 2019
parent "David Nadlinger" <code klickverbot.at> writes:
On 5 May 2019, at 21:57, Mike Franklin via digitalmars-d-ldc wrote:
 Iain fixed a similar issue a few years ago.  I'm not sure if it's 
 related or not: See the last comment here:  
 https://issues.dlang.org/show_bug.cgi?id=14758
I haven't looked at that report in detail, but sure, making the string literals named symbols is a possible workaround. It would just be nice to avoid having to do that manually and instead have LLVM emit them in whatever way appropriate to get both constant merging (where applicable) and linker garbage collection. — David
May 05 2019
prev sibling parent reply Jack Applegame <japplegame gmail.com> writes:
On Saturday, 4 May 2019 at 19:06:26 UTC, kinke wrote:
 On Saturday, 4 May 2019 at 18:37:40 UTC, Jack Applegame wrote:
 And why `-data-sections` flag also doesn't change anything?
This seems to be the perfectly corresponding C++ question (string literals placed shared readonly section) with a nice answer: https://stackoverflow.com/questions/54996229/is-ffunction-sections-fdata-sections-and-gc-sections-not-working LDC emits these strings as private constants in LLVM IR.
How difficult to fix it? I could donate money for the work.
May 08 2019
parent reply kinke <noone nowhere.com> writes:
On Wednesday, 8 May 2019 at 09:18:23 UTC, Jack Applegame wrote:
 How difficult to fix it? I could donate money for the work.
Should be straight-forward, but I fully agree with David and would rather have LLVM provide that functionality - maybe it already does and we just don't know about it yet. ;)
May 08 2019
parent reply Jack Applegame <japplegame gmail.com> writes:
On Wednesday, 8 May 2019 at 15:16:26 UTC, kinke wrote:
 On Wednesday, 8 May 2019 at 09:18:23 UTC, Jack Applegame wrote:
 How difficult to fix it? I could donate money for the work.
Should be straight-forward, but I fully agree with David and would rather have LLVM provide that functionality - maybe it already does and we just don't know about it yet. ;)
I tried to use `lld` instead of `arm-none-eabi-ld` and got some interesting results. `lld` successfully removed unused string constants. I found that there is special SFH_MERGE flag. The linker should remove unused constants and merge duplicates in sections marked with this flag. But it seems that the GNU linker ignores it.
May 09 2019
parent kinke <noone nowhere.com> writes:
On Thursday, 9 May 2019 at 11:23:27 UTC, Jack Applegame wrote:
 I tried to use `lld` instead of `arm-none-eabi-ld` and got some 
 interesting results.
 `lld` successfully removed unused string constants.

 I found that there is special SFH_MERGE flag. The linker should 
 remove unused constants and merge duplicates in sections marked 
 with this flag. But it seems that the GNU linker ignores it.
Ah, nice. [A non-ancient version of] gold may strip them too then (maybe even recent version of bfd), according to this snippet from the gcc bugzilla linked above (from 2015):
 [...] perhaps ld's --gc-sections or new special option should 
 just remove unused string literals from mergeable sections.
I believe (I've read, but I haven't verified) that Gold already does this.
May 09 2019
prev sibling parent reply Mike Franklin <slavo5150 yahoo.com> writes:
On Wednesday, 1 May 2019 at 21:55:09 UTC, Jack Applegame wrote:

 LDC compiles `assert(0)` to `_d_assert(file, line)` call and 
 puts file name (test.d) to section `.rodata.str1.1`:

 ```
 Contents of section .rodata.str1.1:
  0000 74657374 2e466f6f 2e426172 00746573  test.Foo.Bar.tes
  0010 742e466f 6f007465 73742e64 00        t.Foo.test.d.
 ```

 The problem is that this section also contains symbols 
 `test.Foo.Bar` and `test.Foo`. I don't know why these symbols 
 are needed, but they are definitely not used in the program. 
 And because they are in the same section as `test.d`, this 
 whole section goes into firmware.

 In my real application, such useless data occupy an 
 unacceptable amount of flash memory of the MCU. It would be 
 nice to get rid of them.
If you'd like to see a more complete cortex-m project, please see https://github.com/JinShil/stm32f42_discovery_demo You can see how I compile with ldc2 at https://github.com/JinShil/stm32f42_discovery_demo/blob/2f6419de1c30179a85c07e0bf1e3ddd026ace93c/build.d#L78-L88 The technique I use in that project is to create my own minimal runtime: https://github.com/JinShil/stm32f42_discovery_demo/tree/master/source/runtime It just contains the runtime implementations that I need; nothing more. If you want to have support for asserts, you'll have to implement the runtime hooks as shown here: https://github.com/JinShil/stm32f42_discovery_demo/blob/master/source/runtime/exception.d Note that it's ok for your .o files be full of junk. They can be stripped out at link time with the `--gc-sections` flag. Just be sure you're compiling with `-ffunction-sections` and `-fdata-sections` for `--gc-sections` to work well. Question for LDC developers: Are the above compiler flags enabled by default? How can one confirm? You can start your minimal runtime project with just an empty `object.d`: object.d ``` module object; ``` test.d ``` module test; struct Foo { struct Bar { struct Baz { } } } void foo() { assert(0); } ``` ``` ldc2 -conf= -c -mtriple=thumb-none--eabi -mcpu=cortex-m3 test.d arm-none-eabi-size test.o text data bss dec hex filename 48 0 0 48 30 test.o ``` Compare that without the object.d. When the compiler detects a local object.d file, it will use it instead of the runtime. The `-conf=` tells the compiler not to use the default configuration that imports the runtime that comes bundled with the compiler. Compile with `-v` and compare with and without the `-conf=` flag to see the difference. If this just prompts more questions, let them fly. Mike
May 02 2019
next sibling parent reply Mike Franklin <slavo5150 yahoo.com> writes:
On Friday, 3 May 2019 at 03:00:43 UTC, Mike Franklin wrote:

 Note that it's ok for your .o files be full of junk.  They can 
 be stripped out at link time with the `--gc-sections` flag.  
 Just be sure you're compiling with `-ffunction-sections` and 
 `-fdata-sections` for `--gc-sections` to work well.

 Question for LDC developers:  Are the above compiler flags 
 enabled by default?  How can one confirm?
This looks relevant: https://github.com/ldc-developers/ldc/blob/c81a0c94e535c3d670a4fab7aca9b1de22c3778c/driver/targetmachine.cpp#L472-L481 Mike
May 02 2019
parent reply kinke <noone nowhere.com> writes:
On Friday, 3 May 2019 at 03:18:00 UTC, Mike Franklin wrote:
 Question for LDC developers:  Are the above compiler flags 
 enabled by default?  How can one confirm?
This looks relevant: https://github.com/ldc-developers/ldc/blob/c81a0c94e535c3d670a4fab7aca9b1de22c3778c/driver/targetmachine.cpp#L472-L481
Yep, and this for the linker cmdline: https://github.com/ldc-developers/ldc/blob/13cc3c4ed2f4e77096313916e55ce460f9dd1ddc/driver/linker-gcc.cpp#L535-L543 So yes, these are the default settings for Linux targets (the linker-strip-dead option is enabled by default), even for debug builds. For non-Linux targets, we rely on the LLVM defaults wrt. func/data sections; --gc-section is definitely only used for Linux targets though (use `-v` in the LDC cmdline to print the linker cmdline).
May 03 2019
parent reply Mike Franklin <slavo5150 yahoo.com> writes:
On Friday, 3 May 2019 at 16:31:34 UTC, kinke wrote:
 On Friday, 3 May 2019 at 03:18:00 UTC, Mike Franklin wrote:
 Question for LDC developers:  Are the above compiler flags 
 enabled by default?  How can one confirm?
This looks relevant: https://github.com/ldc-developers/ldc/blob/c81a0c94e535c3d670a4fab7aca9b1de22c3778c/driver/targetmachine.cpp#L472-L481
Yep, and this for the linker cmdline: https://github.com/ldc-developers/ldc/blob/13cc3c4ed2f4e77096313916e55ce460f9dd1ddc/driver/linker-gcc.cpp#L535-L543 So yes, these are the default settings for Linux targets (the linker-strip-dead option is enabled by default), even for debug builds. For non-Linux targets, we rely on the LLVM defaults wrt. func/data sections; --gc-section is definitely only used for Linux targets though (use `-v` in the LDC cmdline to print the linker cmdline).
What about `arm-none-eabi`? There's no "linux" in that triple. Is there any way to pass the equivalent of `-ffunction-sections` and `-fdata-sections` on the ldc2 command line?
May 03 2019
parent kinke <noone nowhere.com> writes:
On Saturday, 4 May 2019 at 00:51:16 UTC, Mike Franklin wrote:
  Is there any way to pass the equivalent of 
 `-ffunction-sections` and `-fdata-sections` on the ldc2 command 
 line?
Yep, just strip the `f` prefix - `ldc2 -help-hidden | grep sections`
May 03 2019
prev sibling parent Jack Applegame <japplegame gmail.com> writes:
On Friday, 3 May 2019 at 03:00:43 UTC, Mike Franklin wrote:
 Note that it's ok for your .o files be full of junk.  They can 
 be stripped out at link time with the `--gc-sections` flag.  
 Just be sure you're compiling with `-ffunction-sections` and 
 `-fdata-sections` for `--gc-sections` to work well.
I'm already using `--gc-sections` flag. The junk gets into the same section as useful data. In this case `--gc-sections` flag doesn't help. Also `-data-sections` and `-function-sections` doesn't help too.
 ldc2 -conf= -c -mtriple=thumb-none--eabi -mcpu=cortex-m3 test.d
Wow! Result looks nice. Thanks. But unfortunately `-conf=` flag also makes impossible to use the standard library at compile time. I was also inspired by your `MMIO` library. Great idea! By the way, I personally prefer to use `interface` instead of `final abstract class`.
May 04 2019