[llvm-dev] Generating C headers from LLVM

Peter Lammich via llvm-dev llvm-dev at lists.llvm.org
Fri Apr 12 14:35:14 PDT 2019


Thanks Michael and Johannes for the replies.

> However, the function is defined in LLVM-IR as
> > > {i64,i64,i64} @create_test()
> > 
> > Where are you getting this definition from? Clang outputs what is
> > required by the target backend to generate the correct >ABI. 
> > The mapping
> > from C code to llvm ir is always target dependent. 
> - Michael Spencer> I'm also confused about this part. 

I generate LLVM-IR code from my own frontend language, and that happens
to generate things like the "create_test()" from above. I always
thought this is valid LLVM, and llc will translate it to valid code for
(almost) whatever target I choose. In my case, I have x86_64 Linux. 

Now, I want to call the procedures that my own frontend generates (e.g.
the create_test()) from a C program. I hoped to be able to use clang
for that.


> > > Questions:
> > > 1) Is there any way to convince clang to generate the "correct"
> > > output,
> > > that fits the given definition in LLVM-IR?
> Could you elaborate what you would call "correct output", what
> "incorrect output" you currently see, and how you generate the
> latter?

Given the LLVM-IR definition (say in file test.ll)
  {i64,i64,i64} > @create_test() { ... }

somehow generate a declaration in C for it. When I try 
(say in file invoke.c) 

  typedef struct {int64_t a; int64_t b;int64_t c;} test;
  test create_test(void);yields the LLVM code

  int main([...]) { test x = create_test(); HERE:  [...] }	

and compile with 
  > clang test.ll invoke.c

the generated binary just crashes, and at HERE:, x contains garbage. I
believe this is due to different calling conventions being used. 
When I invoke 
  clang -S -emit-llvm invoke.c
then I see that clang has produced 
  declare void @create_test(%struct.test* sret)
which is "incorrect" for my purpose, as it doesn't match the definition
of create_test() in test.ll.


Note that I have successfully done this with 2-element structures,
e.g., with {i64,i64} the above example just works. That's why I asked
for "other surprises" 
> > > 2) What other surprises to expect? Is there a "safe fragment"
> > > where the
> > >  obvious C code actually matches the obvious LLVM-IR?
> This is a though question. Probably, depending on the target, but Idk
> if
> it is written down. You can try to change the target architecture to
> extend this subset* but as Michael noted above, LLVM-IR is always
> target
> dependent.

I have no problem with being target dependent, as long as I can match
the LLVM-IR definition with a C declaration.


> > > 
> > > 3) If 1 does not exist, is there a way to generate "wrapper-
> > > functions"
> > > in LLVM-IR, that map the given functions to what clang expects?
> I'm not 100% sure I get your question but maybe it helps to remember
> that there is a (target dependent) N to 1 mapping between C
> (signatures)
> and LLVM-IR (types). That being said, it is probably possible to
> "remember" the original C type and map generated IR back, we'll hope
> to
> explore this during the GSoC.

In my use-case, the "original" type comes from my own frontend/LLVM-IR, 
and I want to generate a compatible C type for it.

I hoped to keep my frontend simple, and that's why it just generates
functions that return structure types. However, I need to call these
functions from clang, ideally without clobbering my frontend with
target-specific calling-convention implementations (Conceptually, those
things belong to the backend!). Note that it is irrelevant for me
whether my functions adhere to some specific ABI, as long as I can call
them from C code compiled with clang.


Best,
  Peter



More information about the llvm-dev mailing list