Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to declare a function in LLVM and define it later

Tags:

c++

llvm

llvm-ir

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.

like image 372
Marco A. Avatar asked Mar 10 '14 20:03

Marco A.


People also ask

How is a function declared in?

A function declaration tells the compiler about a function name and how to call the function. The actual body of the function can be defined separately. int max(int, int); Function declaration is required when you define a function in one source file and you call that function in another file.

How do you find the argument of a function in LLVM?

You can use Function::getArgumentList() method to get a list of function's arguments.

What is NSW in LLVM?

• nsw – no signed wrap for add, sub, mul, shl. • nuw – no unsigned wrap for add, sub, mul, shl.

What is LLVM passes?

All LLVM passes are subclasses of the Pass class, which implement functionality by overriding virtual methods inherited from Pass .


1 Answers

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
like image 51
osgx Avatar answered Sep 24 '22 11:09

osgx