setting up LLVM to *run on* amd64 but *generate code* for alpha

I'm trying to persuade llvm (svn trunk) to build in a mode where it
*runs on* amd64 but *generates code* for alpha, exclusively. (Well,
technically, generate code for my experimental architecture simulator
that happens to be based on alpha.) I have been unable to find any
combination of configure switches that makes this happen. I should
probably underline that I am _not_ trying to cross-compile LLVM, I am
trying to make LLVM _be_ a cross compiler.

- The "natural" way to do that (by which I mean "the way you would do
it if you believe what it says in the autoconf manual") would be to
specify --build=x86_64-unknown-linux --target=alpha-unknown-linux.
This produces Makefiles that bomb out on the very first file in the
tree:

$ make
llvm[1]: Compiling Alarm.cpp for Debug build
cc1plus: error: unrecognized command line option "-mieee"
cc1plus: error: unrecognized command line option "-mieee"

because Makefile.config has ARCH=Alpha, and Makefile.rules changes the
options passed to the build compiler based on ARCH. IMO this is a
bug, but I don't understand your makefile system well enough to fix
it.

- The other obvious thing to try is not giving any --build or
--target options but instead --enable-targets=alpha. This builds
successfully but produces llvmc and clang binaries that generate code
for x86_64 by default, and spit out a "unrecognized architecture"
error if I give -arch=alpha.

I have some other, closely-related questions:

- I assume I need a cross-assembler and -linker. Will GNU binutils
in cross-architecture mode work for that? How do I persuade it to use
them? It seems to be setting itself up to feed Alpha code to "as"
instead of "<target-triplet>-as" which isn't going to work.
- Does clang have the necessary code to support Alpha? I noticed
some very architecture-specific-looking code in there, to do with
calling conventions; I'm basically going to have to write that from
scratch for my modified architecture anyway but it would be nice to
know for sure whether it already had the baseline support. (I'm
avoiding llvm-gcc because I know from extensive prior experience with
GCC that it almost certainly cannot handle the semantics of my
modifications at all.)

Thanks,
zw

Hi Zack,

I'm trying to persuade llvm (svn trunk) to build in a mode where it
*runs on* amd64 but *generates code* for alpha, exclusively. (Well,
technically, generate code for my experimental architecture simulator
that happens to be based on alpha.) I have been unable to find any
combination of configure switches that makes this happen. I should
probably underline that I am _not_ trying to cross-compile LLVM, I am
trying to make LLVM _be_ a cross compiler.

- The "natural" way to do that (by which I mean "the way you would do
it if you believe what it says in the autoconf manual") would be to
specify --build=x86_64-unknown-linux --target=alpha-unknown-linux.
This produces Makefiles that bomb out on the very first file in the
tree:

$ make
llvm[1]: Compiling Alarm.cpp for Debug build
cc1plus: error: unrecognized command line option "-mieee"
cc1plus: error: unrecognized command line option "-mieee"

because Makefile.config has ARCH=Alpha, and Makefile.rules changes the
options passed to the build compiler based on ARCH. IMO this is a
bug, but I don't understand your makefile system well enough to fix
it.

LLVM has different back-ends that it generates. These back-ends are
loaded when needed. You select them with the "-march" option of the
"llc" tool. What you're trying to do here is have the LLVM *binaries*
be Alpha binaries. That won't work for you. For instance, the compiler
you're using to compile LLVM doesn't appear to support generating
Alpha binaries.

- The other obvious thing to try is not giving any --build or
--target options but instead --enable-targets=alpha. This builds
successfully but produces llvmc and clang binaries that generate code
for x86_64 by default, and spit out a "unrecognized architecture"
error if I give -arch=alpha.

llvmc will wrap around the llvm-gcc executable. If your built llvm-gcc
doesn't allow the "-arch" flag, then that would be the reason. I don't
think that the shipped llvm-gcc supports Alpha. I don't use "llvmc",
though, so I'm not sure how to help you with this.

I have some other, closely-related questions:

- I assume I need a cross-assembler and -linker. Will GNU binutils
in cross-architecture mode work for that? How do I persuade it to use
them? It seems to be setting itself up to feed Alpha code to "as"
instead of "<target-triplet>-as" which isn't going to work.

You are going to have to build llvm-gcc as a cross-compiler so that
you can get the features you are wanting here. By default, llvm-gcc is
built for the host platform, so there are no need for such
<target-triplet> drivers.

-bw

I'm trying to persuade llvm (svn trunk) to build in a mode where it
*runs on* amd64 but *generates code* for alpha, exclusively.

...

- The "natural" way to do that (by which I mean "the way you would do
it if you believe what it says in the autoconf manual") would be to
specify --build=x86_64-unknown-linux --target=alpha-unknown-linux.
This produces Makefiles that bomb out on the very first file in the
tree:

$ make
llvm[1]: Compiling Alarm.cpp for Debug build
cc1plus: error: unrecognized command line option "-mieee"
cc1plus: error: unrecognized command line option "-mieee"

because Makefile.config has ARCH=Alpha, and Makefile.rules changes the
options passed to the build compiler based on ARCH. IMO this is a
bug, but I don't understand your makefile system well enough to fix
it.

LLVM has different back-ends that it generates. These back-ends are
loaded when needed. You select them with the "-march" option of the
"llc" tool. What you're trying to do here is have the LLVM *binaries*
be Alpha binaries.

That does appear to be what the makefiles are doing, but that is not
what I want and not what --target is supposed to do; to "have the LLVM
*binaries* be Alpha binaries" I ought to say --build=amd64-linux
--host=alpha-linux and leave --target alone.

Specifying --build and --target but not --host [again, according to
the autoconf manual] is supposed to create binaries that run on the
--build machine and generate code for the --target
machine, which is what I want.

llvmc will wrap around the llvm-gcc executable. If your built llvm-gcc
doesn't allow the "-arch" flag, then that would be the reason. I don't
think that the shipped llvm-gcc supports Alpha. I don't use "llvmc",
though, so I'm not sure how to help you with this.

I don't understand this. I am not using llvm-gcc and did not even install it.

You are going to have to build llvm-gcc as a cross-compiler so that
you can get the features you are wanting here. By default, llvm-gcc is
built for the host platform, so there are no need for such
<target-triplet> drivers.

Same observation ...

zw

On reflection, the target architecture does not have to be Alpha. My
actual requirements for the 'base' architecture are 64-bit pointers
and no hardware stack. Is there a better-supported target architecture
with those characteristics?

zw

That would be the correct way to do this, but, I suspect no one around here has put in any time to make that work. You can either roll up your sleeves or leave those out and build all targets, and then use the tool specific options to select a different target other than the default one (the one for your build machine).

The bigger picture here is that you don't need to do anything special to build LLVM as a cross compiler. If you just run configure for LLVM without any --target options, the default is to include all the backends. You can then select a particular backend at runtime.

It is only when you build llvm-gcc, which I understand you aren't interested in right now, that you need to specify --target to configure.

After sending this, I went back and re-read your questions one more time and it made me think you know this already. Your questions reminded me of some of my own confusion when moving from gcc to llvm, but it sounds like you're dealing with some things I haven't had to face yet. Good luck!

I'm trying to persuade llvm (svn trunk) to build in a mode where it
*runs on* amd64 but *generates code* for alpha, exclusively.

...

- The "natural" way to do that (by which I mean "the way you would do
it if you believe what it says in the autoconf manual") would be to
specify --build=x86_64-unknown-linux --target=alpha-unknown-linux.
This produces Makefiles that bomb out on the very first file in the
tree:

$ make
llvm[1]: Compiling Alarm.cpp for Debug build
cc1plus: error: unrecognized command line option "-mieee"
cc1plus: error: unrecognized command line option "-mieee"

because Makefile.config has ARCH=Alpha, and Makefile.rules changes the
options passed to the build compiler based on ARCH. IMO this is a
bug, but I don't understand your makefile system well enough to fix
it.

LLVM has different back-ends that it generates. These back-ends are
loaded when needed. You select them with the "-march" option of the
"llc" tool. What you're trying to do here is have the LLVM *binaries*
be Alpha binaries.

That does appear to be what the makefiles are doing, but that is not
what I want and not what --target is supposed to do; to "have the LLVM
*binaries* be Alpha binaries" I ought to say --build=amd64-linux
--host=alpha-linux and leave --target alone.

What point does this serve? We already have the ability to generate
code for any of our supported targets from the build/host machine.

Specifying --build and --target but not --host [again, according to
the autoconf manual] is supposed to create binaries that run on the
--build machine and generate code for the --target
machine, which is what I want.

It makes no sense. I told you how to do that without using these
flags. Why do you insist on using them? Who said that we had to follow
autoconf exactly and support all of it's flags, which are legion in
number?

llvmc will wrap around the llvm-gcc executable. If your built llvm-gcc
doesn't allow the "-arch" flag, then that would be the reason. I don't
think that the shipped llvm-gcc supports Alpha. I don't use "llvmc",
though, so I'm not sure how to help you with this.

I don't understand this. I am not using llvm-gcc and did not even install it.

You are going to have to build llvm-gcc as a cross-compiler so that
you can get the features you are wanting here. By default, llvm-gcc is
built for the host platform, so there are no need for such
<target-triplet> drivers.

Same observation ...

My observation: You mentioned llvmc. That uses llvm-gcc, from what I
understand. Maybe it also uses clang? I don't know. Perhaps you could
use "-v" to see what command it's really using?

-bw

I'm trying to persuade llvm (svn trunk) to build in a mode where it
*runs on* amd64 but *generates code* for alpha, exclusively. (Well,
technically, generate code for my experimental architecture simulator
that happens to be based on alpha.) I have been unable to find any
combination of configure switches that makes this happen. I should
probably underline that I am _not_ trying to cross-compile LLVM, I am
trying to make LLVM _be_ a cross compiler.

What you want is llvm-gcc to be a cross compiler. llvm can be
compiled natively with no extra flags. To generate alpha assembly
from a bytecode, you use
llc -march=alpha

llvm and llc depend on the system assembler so to get binaries you
will need a cross platform linker and an alpha assembler.

- The "natural" way to do that (by which I mean "the way you would do
it if you believe what it says in the autoconf manual") would be to
specify --build=x86_64-unknown-linux --target=alpha-unknown-linux.
This produces Makefiles that bomb out on the very first file in the
tree:

$ make
llvm[1]: Compiling Alarm.cpp for Debug build
cc1plus: error: unrecognized command line option "-mieee"
cc1plus: error: unrecognized command line option "-mieee"

LLVM should be compiled as is for your architecture. It will then be
able to optimize and produce asm for any supported arch (i.e. it is
naturally cross platform). What you are doing is telling the
Makefiles you are building on an Alpha.

because Makefile.config has ARCH=Alpha, and Makefile.rules changes the
options passed to the build compiler based on ARCH. IMO this is a
bug, but I don't understand your makefile system well enough to fix
it.

LLVM is a cross compiler by default, ARCH is the host machine, not the
target machine.

The simplest thing by far is to have a linux alpha system you can
compile code on (rr use M5 in full system simulation mode). (Note I
haven't built llvm-gcc for a while on alpha, and last I knew it died
in libgcc on some of the math routines, but you can use the native
compiler for those. The llvm-gcc executable works).

Andrew

Hi Zack, welcome!

I'm trying to persuade llvm (svn trunk) to build in a mode where it
*runs on* amd64 but *generates code* for alpha, exclusively. (Well,
technically, generate code for my experimental architecture simulator
that happens to be based on alpha.) I have been unable to find any
combination of configure switches that makes this happen. I should
probably underline that I am _not_ trying to cross-compile LLVM, I am
trying to make LLVM _be_ a cross compiler.

Ok. I'm not sure how much of this was clarified by follow up posts, but I'll try to help.

- The "natural" way to do that (by which I mean "the way you would do
it if you believe what it says in the autoconf manual") would be to
specify --build=x86_64-unknown-linux --target=alpha-unknown-linux.
This produces Makefiles that bomb out on the very first file in the
tree:

$ make
llvm[1]: Compiling Alarm.cpp for Debug build
cc1plus: error: unrecognized command line option "-mieee"

because Makefile.config has ARCH=Alpha, and Makefile.rules changes the
options passed to the build compiler based on ARCH. IMO this is a
bug, but I don't understand your makefile system well enough to fix
it.

LLVM and Clang (but not llvm-gcc) use a different approach than the standard autoconf model for building cross tool chains. Instead of configuring the build to specialize it for one target, we just set the list of enabled targets. LLVM is natively cross build aware and the tools can all support multiple targets at once (even dynamically loading them).

To pick a set of targets to build, configure llvm with the --enable-targets=foo option, where foo is "all" (the default) "native" (host target only) or a list of llvm targets to build. This is strictly an optimization to reduce build time of llvm, you should always be safe to just build all targets.

- The other obvious thing to try is not giving any --build or
--target options but instead --enable-targets=alpha. This builds
successfully but produces llvmc and clang binaries that generate code
for x86_64 by default, and spit out a "unrecognized architecture"
error if I give -arch=alpha.

Some random tidbits of advise:

llvmc is still in early development, and I'm not sure what its support for cross-builds are.

The Alpha target (afaik) generally works, but is considered experimental. Andrew L can answer any specific questions about its state.

Clang is under active development, but the C/ObjC compiler is very usable on x86 32/64. The Clang driver OTOH is still under active development, I'd expect it to settle down in the next couple weeks. When it is complete, the clang driver will fully support a couple of modes for doing a cross compile. First, just running "clang foo.c" will build for the native architecture. "clang foo.c -arch alpha" will build the same OS as the current, but target the alpha processor (e.g. linux/x86 -> linux/alpha). You can also fully specify a triple with "clang -triple=x-y-z foo.c".

I have some other, closely-related questions:

- I assume I need a cross-assembler and -linker. Will GNU binutils
in cross-architecture mode work for that?

Yes!

How do I persuade it to use
them? It seems to be setting itself up to feed Alpha code to "as"
instead of "<target-triplet>-as" which isn't going to work.

I don't know, Daniel should be able to help with this. I assume that the new clang driver will be able to handle this somehow. :slight_smile:

- Does clang have the necessary code to support Alpha? I noticed
some very architecture-specific-looking code in there, to do with
calling conventions; I'm basically going to have to write that from
scratch for my modified architecture anyway but it would be nice to
know for sure whether it already had the baseline support. (I'm
avoiding llvm-gcc because I know from extensive prior experience with
GCC that it almost certainly cannot handle the semantics of my
modifications at all.)

Unfortunately, no we don't support alpha in clang yet. The required code (which goes in lib/Basic/Targets.cpp) is twofold: you have to specify the size of the alpha datatypes and alpha predefined macros, and 2) you have to do some calling convention work for lowering.

The second is pretty nasty, but is only needed if you need something fully abi compliant with your host compiler. If you're just using scalars like floats/ints/pointer, you should be ok without doing any of this work. For example calling into libc/libm and other simple libraries like that should generally work. This may be enough for your research purposes. If you have more detailed questions about Clang specifically, I'd recommend emailing the cfe-dev mailing list.

-Chris

You’ll need to configure llvm-gcc with these flags:

–with-as=[path-to-your-as]
–with-ld=[path-to-your-ld]

You’ll also need to have system headers for your target platform ready and specify them in

–with-sysroot=[path]

when you’re configuring llvm-gcc.

Hi Zack, welcome!

I regret to say I'm disappearing again. I was only looking at LLVM
for a class project which is now done with, and I'm not really
interested in compiler development for the fun of it anymore. I do
want to respond to some of the things that you (and others) said...

I'm trying to persuade llvm (svn trunk) to build in a mode where it
*runs on* amd64 but *generates code* for alpha, exclusively.

As a general note, if you're trying to do cross compilation work, it
is important to be able to set the compiler's *default* target
architecture. "Oh, you can just build with support for all targets
and then stick -arch=foobar on the command line" is not good enough,
because setting up a cross compilation environment involves mucking
with a good half-dozen different programs and libraries, none of which
are configured in the same way -- oh, sure, you *can* hack up all
their build systems to pass an extra switch to the compiler, but you
really don't want to have to.

because Makefile.config has ARCH=Alpha, and Makefile.rules changes the
options passed to the build compiler based on ARCH. IMO this is a
bug, but I don't understand your makefile system well enough to fix
it.

LLVM and Clang (but not llvm-gcc) use a different approach than the standard
autoconf model for building cross tool chains. Instead of configuring the
build to specialize it for one target, we just set the list of enabled
targets. LLVM is natively cross build aware and the tools can all support
multiple targets at once (even dynamically loading them).

To pick a set of targets to build, configure llvm with the
--enable-targets=foo option, where foo is "all" (the default) "native" (host
target only) or a list of llvm targets to build. This is strictly an
optimization to reduce build time of llvm, you should always be safe to just
build all targets.

I don't like this answer. :wink:

It is really really important for everything that has a "configure"
script to support the baseline set of options defined by Autoconf,
*with the semantics described in the Autoconf manual*. It's nice
that LLVM can support more than one target per configuration, but that
doesn't excuse not making --target do something sensible. (Per what I
said above, how about having --target just set the default target, and
if you want to prune the list there's still --enable-targets?)

What --target presently does just makes no sense at all.

I'd also like to mention that, on a one-year-old IBM laptop, building
all the LLVM back-ends takes about three times as long as just
building one of them.

-- I don't mean to be ragging on y'all, but the fact is that I gave up
on LLVM and went back to GCC for my project because of these build
problems. I don't know if it would have been easier to make the
modifications to LLVM that I had in mind than the modifications I
ended up making to GCC -- but I didn't waste nearly a week trying to
get a working cross toolchain with GCC.

zw

Hi Zack, welcome!

I regret to say I'm disappearing again. I was only looking at LLVM
for a class project which is now done with, and I'm not really
interested in compiler development for the fun of it anymore. I do
want to respond to some of the things that you (and others) said...

Sure, feedback is always welcome.

To pick a set of targets to build, configure llvm with the

--enable-targets=foo option, where foo is "all" (the default) "native" (host
target only) or a list of llvm targets to build. This is strictly an
optimization to reduce build time of llvm, you should always be safe to just
build all targets.

I don't like this answer. :wink:

I think that there are several reasons for this. At the end of the day, this is a volunteer project driven by the interests of the community members. Since no one has yet been interested in making what you needed happen, it doesn't work smoothly yet. This is unfortunate but unlikely to get better until someone makes it happen.

It is really really important for everything that has a "configure"
script to support the baseline set of options defined by Autoconf,
*with the semantics described in the Autoconf manual*.

Sure, we have that. If you were asking about llvm-gcc, I could have explained how to do that very simply. You were asking about LLVM (a generic framework for building compilers out of) and clang (which is not fully mature and doesn't have this sort of thing yet) so you got the "current answer".

It's nice
that LLVM can support more than one target per configuration, but that
doesn't excuse not making --target do something sensible. (Per what I
said above, how about having --target just set the default target, and
if you want to prune the list there's still --enable-targets?)

What --target presently does just makes no sense at all.

Agreed, it would be nice for someone to fix that if there cared enough :).

I'd also like to mention that, on a one-year-old IBM laptop, building
all the LLVM back-ends takes about three times as long as just
building one of them.

That's exactly why we have --enable-targets.

-- I don't mean to be ragging on y'all, but the fact is that I gave up
on LLVM and went back to GCC for my project because of these build
problems. I don't know if it would have been easier to make the
modifications to LLVM that I had in mind than the modifications I
ended up making to GCC -- but I didn't waste nearly a week trying to
get a working cross toolchain with GCC.

It's unfortunate to hear that, but it sounds like you made the right choice. If you are uninterested in investing in solving the problems you hit and would not derive any benefit from the capabilities that LLVM provides, then using GCC is an extremely reasonable thing to do.

-Chris

This then may be a documentation problem more than anything else; the
website gave the impression that it wasn't actually necessary to build
llvm-gcc, just download the binaries and put them next to a build of
llvm core. Also, it was not clear to me which of llvm-gcc and clang
was a more appropriate choice for the kind of project I was doing, so
I picked the "native" one... perhaps that was the real mistake.

zw

I'm use to build library using the Apple gcc cross compiler (which works exactly like that, you have to pass arch for everything) and it's not a major issue:

./configure CC="gcc -arch pcc" CXX="g++ -arch pcc"

That works great with anything that uses autoconf-style ./configure,
but that is by no means everything.

zw