adding header files to code

I was wondering how to add header files to code in LLVM. I am trying to create a small profiler to track the actual time spent in functions.
For this i am adding call to clock() in the C code of the given program. However this will require adding the file time.h to C code. Can some tell me a way to do so.
I have tried using Module.addLibrary(“time.h”); but this doesn’t seem to address the problem because I am not able to get the type clock_t by using Module.getType() .Moreover only adding just the module.addlibrary does not add the header file in the generated c code.
It would be a great help if someone could shed light as to how to introduce header files by a transformation pass and able to use the types defined in the header file in the pass itself.
A similar scenario can arise in a parallelizing transformation where one is trying to create threads but this requires inclusion of pthread.h to access the types like pthread_t. etc.

You have to add time.h when you compile the original C-code to LLVM IR. LLVM has no notion of C-header files, so you cannot add a C header file to a module. If you then want the type for clock_t you can lookup the clock function declaration in the LLVM module and ask for its type.


Kshitiz Garg wrote:

Hi Kshitiz,

You can achieve the result you want, but I don't think you can do it in a "clean" way. For one, clock()'s result should be divided by CLOCKS_PER_SEC which is a macro and therefore it will never going to make it past the preprocessor. In other words, your optimization pass cannot emit code that uses CLOCKS_PER_SEC as a variable. You have to assume that its value (1,000,000) is fixed across all environments you want your pass to be used in, and hardcode the value. If you do that though, you can also assume that "clock_t" will be always "long int" and solve your original problem. If you think of it though, you would have to make an assumption along these lines anyway. If not, what would your optimization pass do with the return value of clock()?

Alternatively, you could follow a "two phases" approach. Write a small program that includes all the appropriate headers and uses the functions and/or macros your opt pass needs to insert in the target code, and distribute that little program with your pass. Then in phase one compile that program with LLVM and have another pass (say p0) look at the types/constants the front end generated based on the local headers. At this point, p0 can save in a configuration file all this info. Then, in phase two, your real optimization pass, p1, can read that configuration file and figure out the real sizes, constants, etc.

I hope this helps,