Hello all,
I decided to start trying out the ARM embedded programming ideas
in Adam Ruppe's D Cookbook. Speaking as a complete newcomer to
this area of programming, I was wondering: although Adam advises
using GDC in his tutorials, would it be possible to use LDC
instead -- and if so, what to use in place of the calls to
arm-gdcproject-linux-gnueabi-gdc,
arm-gdcproject-linux-gnueabi-as, arm-gdcproject-linux-gnueabi-ld,
and arm-gdcproject-linux-gnueabi-objcopy ... ?
I'm building LDC on top of llvm 3.4, so is the ARM support here
adequate in any case?
Thanks & best wishes,
-- Joe

Hello all,
I decided to start trying out the ARM embedded programming
ideas in Adam Ruppe's D Cookbook. Speaking as a complete
newcomer to this area of programming, I was wondering: although
Adam advises using GDC in his tutorials, would it be possible
to use LDC instead -- and if so, what to use in place of the
calls to arm-gdcproject-linux-gnueabi-gdc,
arm-gdcproject-linux-gnueabi-as,
arm-gdcproject-linux-gnueabi-ld, and
arm-gdcproject-linux-gnueabi-objcopy ... ?
I'm building LDC on top of llvm 3.4, so is the ARM support here
adequate in any case?
Thanks & best wishes,
-- Joe

Cortex-M, I believe. But as all I'm doing for now is
qemu-based I guess I can adapt to either.

The very first compiler I used to make my semihosted hello world
(http://wiki.dlang.org/Minimal_semihosted_ARM_Cortex-M_%22Hello_World%22)
was LDC. I haven't used it in while, though I intend to when I
get a little farther with my project.
Once again, my goal was to have a compiler that I could use to
create a D runtime, so I didn't need phobos or the D Runtime. I
don't know how many people know this, but you don't actually need
the D Runtime to program in D. You just have to keep yourself
limited to a C-like subset of D.
If you want to use structs, however, you will need to give the
compiler some phony TypeInfo stuff from the object.d/di file.
See my example here:
(https://github.com/JinShil/D_Runtime_ARM_Cortex-M_study/blob/master/1.3-struc
s/source/object.d).
I wrote a wiki about this too
(https://github.com/JinShil/D_Runtime_ARM_Cortex-M_study/wiki/1.3-Structs).
This also needs to be done for GDC. LDC would crash if I did
not provide them
(https://github.com/ldc-developers/ldc/issues/552). Some of
these issues seem to have been fixed
(https://github.com/ldc-developers/ldc/issues/551), but I haven't
gotten around to testing them and providing feedback.
Adam Ruppe actually recommended a potential solution to this
nonsense (https://issues.dlang.org/show_bug.cgi?id=12270).
Also with LDC, I don't think there is a linker capable of
creating an executable for ARM Cortex-M. You can build binutils,
or you can use the linker from here GNU Tools for ARM Embedded
(https://launchpad.net/gcc-arm-embedded).
LDC folks, Does LLVM have its own linker?
LDC also needs to be built with an ARM Thumb LLVM backend. I did
this, but I lost my script files :( I'll have to recreate them.
I remember it being much simpler than GDC. I've asked the LDC
folks to include an ARM Thumb backend in their release, but I
don't think they've done it yet. On Arch Linux, the LDC package
seems to already include ARM Thumb:
ldc2 --version
LDC - the LLVM D compiler (0.13.0):
based on DMD v2.064 and LLVM 3.4.2
Default target: x86_64-unknown-linux-gnu
Host CPU: corei7
http://dlang.org - http://wiki.dlang.org/LDC
Registered Targets:
aarch64 - AArch64 (ARM 64-bit target)
arm - ARM
cpp - C++ backend
hexagon - Hexagon
mips - Mips
mips64 - Mips64 [experimental]
mips64el - Mips64el [experimental]
mipsel - Mipsel
msp430 - MSP430 [experimental]
nvptx - NVIDIA PTX 32-bit
nvptx64 - NVIDIA PTX 64-bit
ppc32 - PowerPC 32
ppc64 - PowerPC 64
ppc64le - PowerPC 64 LE
r600 - AMD GPUs HD2XXX-HD6XXX
sparc - Sparc
sparcv9 - Sparc V9
systemz - SystemZ
thumb - Thumb
x86 - 32-bit X86: Pentium-Pro and above
x86-64 - 64-bit X86: EM64T and AMD64
xcore - XCore
Mike

btw if you have any suggestions for building default gdc / ldc
packages in Arch Linux to make those better suitable for embedded
experiments, please either write me via public dicebot.lv or add
an issue here : https://github.com/Dicebot/Arch-PKGBUILDs
I am very interested in making this experience as easy to try out
as possible for random intrigued by-passers.

btw if you have any suggestions for building default gdc / ldc
packages in Arch Linux to make those better suitable for
embedded experiments, please either write me via
public dicebot.lv or add an issue here :
https://github.com/Dicebot/Arch-PKGBUILDs
I am very interested in making this experience as easy to try
out as possible for random intrigued by-passers.

I think if users are somehow aware that there will be no runtime
or phobos it may be ok to create a distributable package. But if
user's expect everything to just work, they may come away
disappointed.
We may be able to bundle the newlib C library and a phony
object.d for the runtime. But, I wouldn't want users' first
experience with D on microcontrollers to leave them with a bad
taste in their mouth. I'll have to think about it some more.
I'm not sure right now.

I think if users are somehow aware that there will be no
runtime or phobos it may be ok to create a distributable
package. But if user's expect everything to just work, they
may come away disappointed.
We may be able to bundle the newlib C library and a phony
object.d for the runtime. But, I wouldn't want users' first
experience with D on microcontrollers to leave them with a bad
taste in their mouth. I'll have to think about it some more.
I'm not sure right now.

I currently define runtime/phobos as virtual dependencies so it
is perfectly possible to provide alternative runtime package
tuned for microcontrollers.

As there are still serious problems with cross compiling we do
only provide binaries for x86 / x86_64 targets.
As soon as I have fixed the floating point issue (see
https://github.com/ldc-developers/ldc/pull/643) it makes sense to
provide binaries with more targets.
Regards,
Kai

As there are still serious problems with cross compiling we do
only provide binaries for x86 / x86_64 targets.
As soon as I have fixed the floating point issue (see
https://github.com/ldc-developers/ldc/pull/643) it makes sense
to provide binaries with more targets.

Can you make available whatever scripts/patches/config you're
currently using to cross-compile for ARM? I want to try it out,
in preparation for getting Android/ARM working.

As there are still serious problems with cross compiling we do
only provide binaries for x86 / x86_64 targets.
As soon as I have fixed the floating point issue (see
https://github.com/ldc-developers/ldc/pull/643) it makes sense
to provide binaries with more targets.

Can you make available whatever scripts/patches/config you're
currently using to cross-compile for ARM? I want to try it
out, in preparation for getting Android/ARM working.

For cross-compiling you need to use the pull request 643. Setting
CC to the right gcc compiler (gcc-linux-arm) should be all you
have to do.
Regards,
Kai

As there are still serious problems with cross compiling we
do only provide binaries for x86 / x86_64 targets.
As soon as I have fixed the floating point issue (see
https://github.com/ldc-developers/ldc/pull/643) it makes
sense to provide binaries with more targets.

Can you make available whatever scripts/patches/config you're
currently using to cross-compile for ARM? I want to try it
out, in preparation for getting Android/ARM working.

For cross-compiling you need to use the pull request 643.
Setting CC to the right gcc compiler (gcc-linux-arm) should be
all you have to do.

Thanks for the info, I'll try your pull request.
What does setting CC to gcc-linux-arm do, invoke the ARM linker?
How do I make sure druntime/phobos are compiled for ARM?
Just so it's clear, I want to compile ldc as a linux/x86 binary
that will generate ARM code on an x86 host, then compile
druntime, phobos, and their unit tests as ARM libraries/binaries
to deploy to an ARM target.

As there are still serious problems with cross compiling we
do only provide binaries for x86 / x86_64 targets.
As soon as I have fixed the floating point issue (see
https://github.com/ldc-developers/ldc/pull/643) it makes
sense to provide binaries with more targets.

Can you make available whatever scripts/patches/config you're
currently using to cross-compile for ARM? I want to try it
out, in preparation for getting Android/ARM working.

For cross-compiling you need to use the pull request 643.
Setting CC to the right gcc compiler (gcc-linux-arm) should be
all you have to do.

Thanks for the info, I'll try your pull request.
What does setting CC to gcc-linux-arm do, invoke the ARM
linker? How do I make sure druntime/phobos are compiled for
ARM?

Yes, the CC setting is used to invoke the linker.

Just so it's clear, I want to compile ldc as a linux/x86 binary
that will generate ARM code on an x86 host, then compile
druntime, phobos, and their unit tests as ARM
libraries/binaries to deploy to an ARM target.

Cross-compiling druntime/phobos is possible but untried. You
could try to setup host and target compilers in CMakeList.txt or
you could build a small script to compile all .d modules into a
library. There is no out-of-the-box solution.
(Currently I build ldc on an ARM box and avoid the cross
compiling scenario.)
Regards,
Kai

Cross-compiling druntime/phobos is possible but untried. You
could try to setup host and target compilers in CMakeList.txt or
you could build a small script to compile all .d modules into a
library. There is no out-of-the-box solution.
(Currently I build ldc on an ARM box and avoid the cross
compiling scenario.)

Cross-compiling druntime/phobos is possible but untried. You
could try to setup host and target compilers in CMakeList.txt
or
you could build a small script to compile all .d modules into a
library. There is no out-of-the-box solution.
(Currently I build ldc on an ARM box and avoid the cross
compiling scenario.)

An update: by simply following in Dan's footsteps for iOS, but
with slightly different flags for linux/ARM, I've been able to
build an x86 ldc binary and an ARM druntime/phobos in a linux/x86
VM and deploy to a linux/ARM device. :)
I'm able to build the dmd sample program sieve.d for ARMv7 with
all three combinations of ldc alone, ldc and druntime, and ldc
and phobos, with small modifications to sieve.d for writing
output for each case. The first two combos produce an executable
that runs fine on linux/ARM, the one with phobos seems to run and
then prints out junk output.
I had to apply the real/long-double pull #643 to get phobos to
compile for ARM. Right now, I push the objects and static
libraries to the linux/ARM target and link them using the native
linker, as I didn't want to mess with trying to figure out how to
get the x86 linker to link for ARM yet.
I'm going to try cross-compiling and running the unit tests next.
What should I expect?
I'll try merging David's old patch for ARM exception-handling
from issue #489 at some point.

Cross-compiling druntime/phobos is possible but untried. You
could try to setup host and target compilers in CMakeList.txt
or
you could build a small script to compile all .d modules into
a
library. There is no out-of-the-box solution.
(Currently I build ldc on an ARM box and avoid the cross
compiling scenario.)

An update: by simply following in Dan's footsteps for iOS, but
with slightly different flags for linux/ARM, I've been able to
build an x86 ldc binary and an ARM druntime/phobos in a
linux/x86 VM and deploy to a linux/ARM device. :)
I'm able to build the dmd sample program sieve.d for ARMv7 with
all three combinations of ldc alone, ldc and druntime, and ldc
and phobos, with small modifications to sieve.d for writing
output for each case. The first two combos produce an
executable that runs fine on linux/ARM, the one with phobos
seems to run and then prints out junk output.
I had to apply the real/long-double pull #643 to get phobos to
compile for ARM. Right now, I push the objects and static
libraries to the linux/ARM target and link them using the
native linker, as I didn't want to mess with trying to figure
out how to get the x86 linker to link for ARM yet.
I'm going to try cross-compiling and running the unit tests
next.
What should I expect?

I still have trouble with binaries compiled without optimization.
Using -O1 or higher works.

I'll try merging David's old patch for ARM exception-handling
from issue #489 at some point.

I merged the easy part of the patch so expect some merge
conflicts.
BTW: sounds real cool!
Regards,
Kai

My question is more how many of the unit tests should I expect
to run?

Alright, finally got the tests to link and run.
All tests pass for a cross-compiled linux/ARM druntime except for
rt.minfo, which crashes. I noticed that core.internal.convert
and core.internal.hash aren't run by the ldc test scripts, so I
compiled and ran those too. The latter passes, but the former
asserts in one of the conversions and fails. I haven't looked
into which conversion yet, may be related to the real/long double
cross-compiling issues.
As for phobos, three modules' unit tests don't compile for
linux/ARM- std.variant, std.math, and std.traits- and every
single module throws this error when running their tests right
now:
core.exception.RangeError std.string.sformat(0): Range violation
Something basic is going wrong there, will look into it more.
How does this compare to the test runs on ARM that the ldc devs
have tried?

My question is more how many of the unit tests should I expect to run?
[…]
I'll try merging David's old patch for ARM exception-handling from
issue #489 at some point.

When I last tried (which was a _long_ time ago), there were still some
random crashes in the unit tests that looked like they were caused by an
error during unwinding.
Back then, my guess was that there might be a subtle mistake in the
ARM-specific unwinding definitions (type size, field alignment, …) or an
unhandled special case in the code. It's probably fairly easy to figure
out with a more methodical look at the issue, but I was in "get
something to work, now" mode when I hacked up the patch.
Let me know if there are any questions regarding EH that I might be able
to help you with.
Best,
David

On Saturday, 30 August 2014 at 21:58:18 UTC, David Nadlinger via
digitalmars-d-ldc wrote:

When I last tried (which was a _long_ time ago), there were
still some random crashes in the unit tests that looked like
they were caused by an error during unwinding.

If you mean random in the sense that the same test will sometimes
pass and sometimes crash, I haven't seen that.

Back then, my guess was that there might be a subtle mistake in
the ARM-specific unwinding definitions (type size, field
alignment, …) or an unhandled special case in the code. It's
probably fairly easy to figure out with a more methodical look
at the issue, but I was in "get something to work, now" mode
when I hacked up the patch.
Let me know if there are any questions regarding EH that I
might be able to help you with.

I haven't actually looked at either the real/longdouble patch or
your EH patch other than skimming them yet, just applied the two
and tried different ways of building the resulting source. I've
now tried building with gcc and clang, both native and
cross-compile for each, and find almost no difference in the test
runs done each of the four ways. This seems to indicate that a
cross-compile is just as good as native compilation, which is
great because I can cross-compile much faster on a single core of
my core i5 than natively compiling ldc and the unit tests on the
dual Cortex-A7 cores of the Cubieboard2 I'm testing on.
The std.string.sformat issue with the phobos tests that I
mentioned earlier was in a static ctor for std.net.curl. Once I
removed that module from the test runner, I got 4 phobos modules'
tests to pass, 10 modules assert in a test somewhere, 44 seg
fault, and 8 say they "Aborted," so I'm 4/69 on the phobos unit
tests right now (I got std.traits to compile with a small fix).
Is that about what you guys got when you ran the phobos tests on
ARM before?
I can't say if EH is the main issue or if there are other porting
issues, as I haven't started looking into the details yet.

The std.string.sformat issue with the phobos tests that I
mentioned earlier was in a static ctor for std.net.curl. Once
I removed that module from the test runner, I got 4 phobos
modules' tests to pass, 10 modules assert in a test somewhere,
44 seg fault, and 8 say they "Aborted," so I'm 4/69 on the
phobos unit tests right now (I got std.traits to compile with a
small fix). Is that about what you guys got when you ran the
phobos tests on ARM before?
I can't say if EH is the main issue or if there are other
porting issues, as I haven't started looking into the details
yet.

I just tried cross-compiling to ARM with the merge-2.066 branch
and llvm 3.5 and the latter seems to make a bunch of seg faults
go away. :) rt.minfo passes its tests now, but core.time asserts
and so does core.internal.convert still. As for phobos, 3
modules pass, 46 modules assert- 41 of which assert in one test
in std.format, not sure why other modules are running tests for
std.format- only 9 segfault, and 10 are "Aborted," so I'm down to
3/69 now, but hopefully much easier to fix with less segfaults.
I didn't get this improvement with merge-2.066 and llvm 3.4, so
it's definitely llvm 3.5 that made the difference, not sure why.

The std.string.sformat issue with the phobos tests that I
mentioned earlier was in a static ctor for std.net.curl. Once
I removed that module from the test runner, I got 4 phobos
modules' tests to pass, 10 modules assert in a test somewhere,
44 seg fault, and 8 say they "Aborted," so I'm 4/69 on the
phobos unit tests right now (I got std.traits to compile with
a small fix). Is that about what you guys got when you ran
the phobos tests on ARM before?
I can't say if EH is the main issue or if there are other
porting issues, as I haven't started looking into the details
yet.

I just tried cross-compiling to ARM with the merge-2.066 branch
and llvm 3.5 and the latter seems to make a bunch of seg faults
go away. :) rt.minfo passes its tests now, but core.time
asserts and so does core.internal.convert still. As for
phobos, 3 modules pass, 46 modules assert- 41 of which assert
in one test in std.format, not sure why other modules are
running tests for std.format- only 9 segfault, and 10 are
"Aborted," so I'm down to 3/69 now, but hopefully much easier
to fix with less segfaults.
I didn't get this improvement with merge-2.066 and llvm 3.4, so
it's definitely llvm 3.5 that made the difference, not sure why.

More good news, the sieve.d sample file from dmd's repo now not
only compiles fine against phobos but doesn't spit out junk
output anymore, ie it works. I wish all ldc problems could just
be solved by an llvm upgrade like this. ;)

The std.string.sformat issue with the phobos tests that I
mentioned earlier was in a static ctor for std.net.curl.
Once I removed that module from the test runner, I got 4
phobos modules' tests to pass, 10 modules assert in a test
somewhere, 44 seg fault, and 8 say they "Aborted," so I'm
4/69 on the phobos unit tests right now (I got std.traits to
compile with a small fix). Is that about what you guys got
when you ran the phobos tests on ARM before?
I can't say if EH is the main issue or if there are other
porting issues, as I haven't started looking into the details
yet.

I just tried cross-compiling to ARM with the merge-2.066
branch and llvm 3.5 and the latter seems to make a bunch of
seg faults go away. :) rt.minfo passes its tests now, but
core.time asserts and so does core.internal.convert still. As
for phobos, 3 modules pass, 46 modules assert- 41 of which
assert in one test in std.format, not sure why other modules
are running tests for std.format- only 9 segfault, and 10 are
"Aborted," so I'm down to 3/69 now, but hopefully much easier
to fix with less segfaults.
I didn't get this improvement with merge-2.066 and llvm 3.4,
so it's definitely llvm 3.5 that made the difference, not sure
why.

More good news, the sieve.d sample file from dmd's repo now not
only compiles fine against phobos but doesn't spit out junk
output anymore, ie it works. I wish all ldc problems could
just be solved by an llvm upgrade like this. ;)

Yikes, spoke too soon, it prints out the first line and then
segfaults. I guess this is an improvement over junk output.

More good news, the sieve.d sample file from dmd's repo now
not only compiles fine against phobos but doesn't spit out
junk output anymore, ie it works. I wish all ldc problems
could just be solved by an llvm upgrade like this. ;)

Yikes, spoke too soon, it prints out the first line and then
segfaults. I guess this is an improvement over junk output.

Got the segfault in the sieve program to go away by changing the
default calling convention for all linkage types in gen/abi.cpp
to C, just as Kai did on PPC64. I don't get any "Aborted" tests
now either.
One issue cropping up in std.format appears to be with structs
that use alias this for a member, specifically these two:
https://github.com/D-Programming-Language/phobos/blob/master/std/format.d#L1307https://github.com/D-Programming-Language/phobos/blob/master/std/format.d#L1748
The first one returns false, the second one returns a junk number
for the imaginary component of the complex number. Not sure why
it fails for some structs that use alias this and not others,
going to look into it.
Another issue is that the dwarf output for debugging might be
corrupted somehow. If I compile sieve.d and have it run fine
against non-debug druntime/phobos, it then segfaults in different
places if I link it against debug druntime or phobos, which are
simply compiled with the -g flag.
Finally, many modules still claim that they assert in a test in
std.format, when std.format itself says that test passes, weird.

Hey Kai, I see that you just mentioned that you're still trying
ldc on linux/ARM. I never got an answer to my question before:
how many tests pass for you when running on linux/ARM? I've
detailed my results here: most of druntime passes while most of
phobos doesn't.

Another issue is that the dwarf output for debugging might be
corrupted somehow. If I compile sieve.d and have it run fine
against non-debug druntime/phobos, it then segfaults in
different places if I link it against debug druntime or phobos,
which are simply compiled with the -g flag.

I figured out what the problem was with debug: it's that
codeGenOptLevel() in gen/optimizer.cpp turns off all
optimizations when generating debug symbols is turned on. As we
both noted previously that ldc is generating buggy code for -O0
with ARM, the problem is with the generated code, not debug
output. If I patch that ldc function so that debug output can be
used with different optimization levels, I can debug again on
linux/ARM if I use an optimization level of -O1 or higher, though
I haven't tested it extensively.
I had tried using different optimization levels with debug
before, but didn't know ldc was silently turning it off till now.
I notice that clang doesn't seem to turn optimization off for
debug and that the ldc patch that turned optimization off is more
than five years old: perhaps it's not necessary?

I decided to start trying out the ARM embedded programming
ideas in Adam Ruppe's D Cookbook. Speaking as a complete
newcomer to this area of programming, I was wondering: although
Adam advises using GDC in his tutorials, would it be possible
to use LDC instead -- and if so, what to use in place of the
calls to arm-gdcproject-linux-gnueabi-gdc,
arm-gdcproject-linux-gnueabi-as,
arm-gdcproject-linux-gnueabi-ld, and
arm-gdcproject-linux-gnueabi-objcopy ... ?
I'm building LDC on top of llvm 3.4, so is the ARM support here
adequate in any case?

You can build LDC on an ARM system without problem. Most stuff
works out of the box. Prominent exceptions are exception handling
and some std.math stuff. Most annoying: there is a bug(?) in
dso_ctor()/dso_dtor() which prevents compiling with -O0. If you
use -O1 or higher everything works.
More likely you want to cross compile to ARM. The problem here is
floating point support as ARM does not have a real (80-bit)
floating point type. Currently, you can't change this without
recompiling LDC. (Change real_t to double and use the double
constants instead of the long double ones.) This is the reason
why the binary distributions do not contain an ARM backend.
llvm 3.4 is ok for code generation. As far as I remember wrong
relocations are generated for debug info of TLS variables.
Just give it a try. :-)
Regards,
Kai