Question

How can I declare a function in LLVM (with a specific signature) and create a call to it, e.g.

llvm::Value* return = m_builder.CreateCall( function, arguments );

but then define the body of the function later (which must be an InlineAsm function) ?

I'm later accessing the functions in a module in the following way

for (llvm::Module::iterator it = mod->begin(), end = mod->end(); it != end; ++it) 
{
     if( needsImplementation(it) ) {
        llvm::InlineAsm* inlineCall = ...
        it.body = inlineCall // This doesn't exist, pseudocode for what I need
     }
}

Since the signature is the same this should be possible I believe.

Was it helpful?

Solution

From the "Kaleidoscope: Code generation to LLVM IR" manual: http://llvm.org/docs/tutorial/LangImpl3.html

3.4. Function Code Generation

Code generation for prototypes and functions must handle a number of details, which make their code less beautiful than expression code generation, but allows us to illustrate some important points. First, lets talk about code generation for prototypes: they are used both for function bodies and external function declarations. The code starts with:

Function *PrototypeAST::Codegen() {
  // Make the function type:  double(double,double) etc.
  std::vector<Type*> Doubles(Args.size(),
                             Type::getDoubleTy(getGlobalContext()));
  FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),
                                       Doubles, false);

  Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule);

Later, when you want to add IR to the function you should get its declaration from the module: TheModule->getFunction(Name); and add a BasicBlock:

BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction);
Builder.SetInsertPoint(BB);

PS: answer is untested and answerer is not expert in LLVM.

PPS: For InlineAsm function, as I think after doing searches with MetaGer, you can't declare function as cited from Kaleidoscope. The only way is to have InlineAsm function created at the place of call. Example of such usage is here: CyanogenMod/android/art/compiler/llvm/runtime_support_builder_x86.cc#44

44 Value* RuntimeSupportBuilderX86::EmitGetCurrentThread() {
45  Function* ori_func = GetRuntimeSupportFunction(runtime_support::GetCurrentThread);
          //  ^^^^^ this is used only to know right Type of Function.
46  std::string inline_asm(StringPrintf("mov %%fs:%d, $0", Thread::SelfOffset().Int32Value()));  // <<< define the body of InlineAsm
47  InlineAsm* func = InlineAsm::get(ori_func->getFunctionType(), inline_asm, "=r", false);  // << Create InlineAsm function
48  CallInst* thread = irb_.CreateCall(func); // << Call it
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top