Как объявить функцию в LLVM и определить ее позже

Как я могу объявить функцию в LLVM (с определенной подписью) и создать для нее вызов, например.

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

но затем определить тело функции позже (которая должна быть функцией InlineAsm)?

Позже я получаю доступ к функциям в модуле следующим образом

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
     }
}

Я считаю, что поскольку подпись та же, это должно быть возможно.


person Marco A.    schedule 10.03.2014    source источник


Ответы (1)


Из руководства «Калейдоскоп: генерация кода для LLVM IR»: http://llvm.org/docs/tutorial/LangImpl3.html

3.4. Генерация функционального кода

Генерация кода для прототипов и функций должна обрабатывать ряд деталей, что делает их код менее красивым, чем генерация кода с помощью выражений, но позволяет нам проиллюстрировать некоторые важные моменты. Во-первых, давайте поговорим о генерации кода для прототипов: они используются как для тел функций, так и для объявлений внешних функций. Код начинается с:

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);

Позже, когда вы захотите добавить IR в функцию, вы должны получить ее объявление из модуля: TheModule->getFunction(Name); и добавить BasicBlock:

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

PS: ответ не проверен, и ответчик не является экспертом в LLVM.

PPS: для функции InlineAsm, как я думаю, после выполняя поиск с помощью MetaGer, вы не можете объявить функцию как цитируемую из Kaleidoscope. Единственный способ - создать функцию InlineAsm в месте вызова. Пример такого использования здесь: 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
person osgx    schedule 10.03.2014
comment
Обновленная ссылка на учебник: llvm.org/docs/tutorial/LangImpl03.html - person vasilyrud; 15.09.2018