Analysis and code generation actions

Dear Clang aficionados,

I’d like to adapt Clang to accept a C extension, perform a bit of analysis and then output LLVM IR.

First, I learnt how to use Sema/ParseAST and CodeGen/ModuleBuilder in the 2.6 release. However, since ParseAST in not re-enterable I can’t do analysis and code generation at the same time. So I’d really appreciate if you could point me to the right way of doing this!

CompilerInstance/CompilerInvocation are definitely the way to do this. You could also build your own FrontendAction that does both analysis and codegen in one shot.

Second, I’m looking to the development branch. I see some great looking API changes, such as introducing CompilerInstance and CompilerInvocation, and a bunch of FrontendActions. I was hoping to use FrontendActions for implementing my analysis and code gen, but no luck so far.

The minimal program

/// \file CompilerInstance.c
#include <clang/Frontend/FrontendActions.h>
int main()
{
clang::EmitLLVMOnlyAction emitLLVM;
}

results in:

lib/VMCore/Pass.cpp:228: void ::PassRegistrar::RegisterPass(const llvm::PassInfo&): Assertion `Inserted && “Pass registered multiple times!”’ failed.

In addition, by trial and error I figured out that I needed to link against many Clang and LLVM libraries, e.g.

g++ ./CompilerInstance.o -lclangFrontend -lclangSema -lclangDriver -lclangAnalysis -lclangChecker -lclangRewrite -lclangAST -lclangCodeGen -lclangLex -lclangBasic -lclangParse -lLLVMScalarOpts -lLLVMInstCombine -lLLVMSelectionDAG -lLLVMipo -lLLVMipa -lLTO -lLLVMTransformUtils -lLLVMBitWriter -lLLVMAnalysis -lLLVMCodeGen -lLLVMCore -lLLVMMC -lLLVMSupport -lLLVMSystem -lLLVMTarget -lm -ldl –lpthread

I find it weird that in order to use a FrontendAction that only emits LLVM code I also need to link against so many optimisation libraries.

When you’re emitting LLVM IR, you naturally end up using LLVM’s optimization infrastructure to handle that IR, so you need to link in that code.

Can I conclude from this experience that FrontendActions are not supposed to be used like this? (The same happens when I first initialise a CompilerInstance properly and then declare an EmitLLVMOnlyAction object.) Again, what would be the right way to do this?

It seems like you’re doing the right thing. You can use llvm-config to help you figure out exactly which libraries you need to link against to get the right back-end bits.

  • Doug

Hi Doug,

Thanks a lot for reassuring me that I’m on the right way! I’m just so
bamboozled by not being able to run even a minimal program. Perhaps I need
to file a bug report for this.

(Again, using gcc 3.4.6 on RHEL4 to compile with r96575

#include <clang/Frontend/FrontendActions.h>
int main() { clang::EmitLLVMOnlyAction emitLLVM; }

results in:

lib/VMCore/Pass.cpp:228: void <unnamed>::PassRegistrar::RegisterPass(const
llvm::PassInfo&): Assertion `Inserted && "Pass registered multiple times!"'
failed.)

When you're emitting LLVM IR, you naturally end up using LLVM's

optimization infrastructure to handle that IR, so you need to link in that
code.

Yes, some of it. But generating LLVM code with clang::CreateLLVMCodeGen
does no optimisations, and hence requires a minimal set of LLVM libraries,
so I thought I'd get the same or similar behaviour when using
clang::EmitLLVMOnlyAction...

Many thanks again,
Anton.