Using LLVM as cross-compiler to C

Hi All - Newbie warning... I am developing for a target that does not have a functioning C++ environment, and need to use C++. It was suggested that I could use LLVM to compile to C (using llc -march=c), then run the resulting C-code through the working C-cross-compilation tools. So, some newbie questions:

(1) Is this crazy ?
(2) What happens to all the C++ RTL ? Is it statically linked as LLVM code, then translated back into C ?
(3) Where does the LLVM RTL come from - newlib ? glibc ? other ?
(4) Is it manageable to create a small number of intrinsics to allow access to the C runtime functions on the target, or is this difficult ? In the mailing list archive I saw some unresolved question with warnings about type conversions for someone trying this...

Thanks in advance for your advice,
Best Regards, Dave

Dave Nadler, USA East Coast voice (978) 263-0097, drn@nadler.com, Skype Dave.Nadler1

Hi All - Newbie warning... I am developing for a target that does not have
a functioning C++ environment, and need to use C++. It was suggested that I
could use LLVM to compile to C (using llc -march=c), then run the resulting
C-code through the working C-cross-compilation tools. So, some newbie
questions:

(1) Is this crazy ?

It depends on you definition of "crazy". It will turn it into C code.
However, you'll still need to link in the libstdc++ library.

(2) What happens to all the C++ RTL ? Is it statically linked as LLVM code,
then translated back into C ?
(3) Where does the LLVM RTL come from - newlib ? glibc ? other ?

LLVM doesn't use RTL. It has its own IR.

(4) Is it manageable to create a small number of intrinsics to allow access
to the C runtime functions on the target, or is this difficult ? In the
mailing list archive I saw some unresolved question with warnings about
type conversions for someone trying this...

I'm not sure I understand your question. The program will have a call
to the C runtime functions (like strtof), and those are compiled into
calls in the assembly language. (Of course, the libc library needs to
be linked in to get the executable.) There are a few C runtime calls
that LLVM handles specially -- like memset, memcpy, etc. But it's not
necessary to have *all* C runtime calls be builtins or intrinsics for
LLVM to handle them.

-bw

Bill Wendling wrote:

  

Hi All - Newbie warning... I am developing for a target that does not have
a functioning C++ environment, and need to use C++. It was suggested that I
could use LLVM to compile to C (using llc -march=c), then run the resulting
C-code through the working C-cross-compilation tools. So, some newbie
questions:

(1) Is this crazy ?
    
It depends on you definition of "crazy". It will turn it into C code.
However, you'll still need to link in the libstdc++ library.
  

One additional problem you may have a C header files. Different
operating systems and C library implementations will implement the same
functions differently, so when cross-compiling, you need to make sure
your compiling against header files that work on your target platform.

(2) What happens to all the C++ RTL ? Is it statically linked as LLVM code,
then translated back into C ?
(3) Where does the LLVM RTL come from - newlib ? glibc ? other ?
    
LLVM doesn't use RTL. It has its own IR.
  

I believe he means the C++ Run-Time Library and not GCC's RTL
Intermediate Representation.

Older versions of llvm-gcc compiled libstdc++ to LLVM bitcode and linked
it statically into the LLVM bitcode for your program. I am not sure
what newer versions of llvm-gcc do.

I do know that libc functions and other system functions are not
compiled into LLVM bitcode. They are (as Bill described below) either
converted into LLVM intrinsics (like memcpy) or become calls to external
functions (like printf). After generation to native code, the program
is linked against the system libraries.

-- John T.

Thanks John and Bill for your feedback.
A bit more detail below...
Thanks again,
Best Regards, Dave

Bill Wendling wrote:
>
>> Hi All - Newbie warning... I am developing for a target that does not have
>> a functioning C++ environment, and need to use C++. It was suggested that I
>> could use LLVM to compile to C (using llc -march=c), then run the resulting
>> C-code through the working C-cross-compilation tools. So, some newbie
>> questions:
>>
>> (1) Is this crazy ?
>>
>
> It depends on you definition of "crazy". It will turn it into C code.
> However, you'll still need to link in the libstdc++ library.
>
One additional problem you may have a C header files. Different
operating systems and C library implementations will implement the same
functions differently, so when cross-compiling, you need to make sure
your compiling against header files that work on your target platform.

Its an bare-metal embedded target, so there is no use of any headers
other than the C and C++ library functions. As long as the versions
with LLVM are standards-compliant, no problem, right ?

>> (2) What happens to all the C++ RTL ? Is it statically linked as LLVM code,
>> then translated back into C ?
>> (3) Where does the LLVM RTL come from - newlib ? glibc ? other ?
>>
> LLVM doesn't use RTL. It has its own IR.
>
I believe he means the C++ Run-Time Library and not GCC's RTL
Intermediate Representation.

Sorry I wasn't clear, yes I meant the C++ runtime library.
Its a two-part question:
- the compiler internals library (for example, exception handling), and
- the "standard" library (for example printf)

Older versions of llvm-gcc compiled libstdc++ to LLVM bitcode and linked
it statically into the LLVM bitcode for your program. I am not sure
what newer versions of llvm-gcc do.

I do know that libc functions and other system functions are not
compiled into LLVM bitcode. They are (as Bill described below) either
converted into LLVM intrinsics (like memcpy) or become calls to external
functions (like printf). After generation to native code, the program
is linked against the system libraries.

-- John T.

>> (4) Is it manageable to create a small number of intrinsics to allow access
>> to the C runtime functions on the target, or is this difficult ? In the
>> mailing list archive I saw some unresolved question with warnings about
>> type conversions for someone trying this...
>>
> I'm not sure I understand your question. The program will have a call
> to the C runtime functions (like strtof), and those are compiled into
> calls in the assembly language. (Of course, the libc library needs to
> be linked in to get the executable.) There are a few C runtime calls
> that LLVM handles specially -- like memset, memcpy, etc. But it's not
> necessary to have *all* C runtime calls be builtins or intrinsics for
> LLVM to handle them.
>
> -bw

Do I understand correctly from above: LLVM provides a version of
the runtime library, of which some routines are converted to "external"
calls already ? So, there's already a printf binding to an external ?
For the standard-C library, my question is:
- how much of this has already been implemented (mapping to external),
- how hard will it be to add additional bindings ?

newlib makes it relatively easy by using common IO routines that
you replace with platform-specific implementations; is there something
analogous in the LLVM library implementation ? Hope I was more
clear this time...

Thanks again for your advice,
Best Regards, Dave

Dave Nadler, USA East Coast voice (978) 263-0097, drn@nadler.com, Skype Dave.Nadler1

One additional problem you may have a C header files. Different
operating systems and C library implementations will implement the same
functions differently, so when cross-compiling, you need to make sure
your compiling against header files that work on your target platform.

Its an bare-metal embedded target, so there is no use of any headers
other than the C and C++ library functions. As long as the versions
with LLVM are standards-compliant, no problem, right ?

Yes.

>> (2) What happens to all the C++ RTL ? Is it statically linked as LLVM
code,
>> then translated back into C ?
>> (3) Where does the LLVM RTL come from - newlib ? glibc ? other ?
>>
> LLVM doesn't use RTL. It has its own IR.
>
I believe he means the C++ Run-Time Library and not GCC's RTL
Intermediate Representation.

Sorry I wasn't clear, yes I meant the C++ runtime library.
Its a two-part question:
- the compiler internals library (for example, exception handling), and
- the "standard" library (for example printf)

We don't convert libstdc++ or libc into LLVM code. It's linked in
as-is from the system. For exception handling, we create ABI-compliant
code. So it's usable by the normal C++ RTL.

>> (4) Is it manageable to create a small number of intrinsics to allow
access
>> to the C runtime functions on the target, or is this difficult ? In the
>> mailing list archive I saw some unresolved question with warnings about
>> type conversions for someone trying this...
>>
> I'm not sure I understand your question. The program will have a call
> to the C runtime functions (like strtof), and those are compiled into
> calls in the assembly language. (Of course, the libc library needs to
> be linked in to get the executable.) There are a few C runtime calls
> that LLVM handles specially -- like memset, memcpy, etc. But it's not
> necessary to have *all* C runtime calls be builtins or intrinsics for
> LLVM to handle them.

Do I understand correctly from above: LLVM provides a version of
the runtime library, of which some routines are converted to "external"
calls already ? So, there's already a printf binding to an external ?
For the standard-C library, my question is:
- how much of this has already been implemented (mapping to external),
- how hard will it be to add additional bindings ?

newlib makes it relatively easy by using common IO routines that
you replace with platform-specific implementations; is there something
analogous in the LLVM library implementation ? Hope I was more
clear this time...

Not really. LLVM doesn't provide the libc or libstdc++ libraries.
Those are expected to be on your system already. There are some C
calls that LLVM recognizes as standard C functions, and that LLVM can
generate efficient code for. It generates assembly code in these
cases, not a call to an external library. I don't know about "newlib",
but if it's a replacement for the normal libc library, there shouldn't
be a problem with using it.

-bw