LLVM 错误无法选择内部 %llvm.coro.begin [英] LLVM Error Cannot select intrinsic %llvm.coro.begin

查看:119
本文介绍了LLVM 错误无法选择内部 %llvm.coro.begin的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习LLVM中的协程功能,并且一直在基于示例.

I am working on learning the coroutine feature in LLVM and have been working on a simple test based on one of the examples from the documents.

当我尝试对生成的位代码运行 llc 时,收到错误消息 LLVM错误:无法选择:固有%llvm.coro.begin .到目前为止,我发现的唯一类似错误是由于某些平台不支持 i1 布尔值,但是我调用的所有内在函数都不使用 i1 .

When I try to run llc on the generated the bitcode, I get the error message LLVM ERROR: Cannot select: intrinsic %llvm.coro.begin. So far, the only similar error I've found was due to some platforms not supporting i1 for boolean, but none of the intrinsics I am calling use i1.

这是LLVM IR,我已删除了对 llvm.coro.begin 的调用后将发生的所有逻辑,以降低发生错误所需的最低限度:

Here is the LLVM IR, I have removed all the logic that would occur after the call to llvm.coro.begin to get down to the minimum necessary for the error to happen:

; ModuleID = 'coro example'
source_filename = "coro example"

; Function Attrs: nounwind readnone
declare i32 @llvm.coro.size.i32() #0

; Function Attrs: argmemonly nounwind readonly
declare token @llvm.coro.id(i32, i8* readnone, i8* nocapture readonly, i8*) #1

; Function Attrs: nounwind
declare i8* @llvm.coro.begin(token, i8* writeonly) #2

define void @test() {
entry:
  %id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
  %size = call i32 @llvm.coro.size.i32()
  %alloc = tail call i8* @malloc(i32 %size)
  %hdl = call i8* @llvm.coro.begin(token %id, i8* %alloc)
  ret void
}

declare noalias i8* @malloc(i32)

attributes #0 = { nounwind readnone }
attributes #1 = { argmemonly nounwind readonly }
attributes #2 = { nounwind }

以及生成以上代码的代码:

and the code which generated the above:

// Get coro intrinsics
std::vector<Type *> types(1, Type::getInt32Ty(*TheContext));
Function *decl_coro_size = Intrinsic::getDeclaration(TheModule.get(), Intrinsic::coro_size, types);
Function *decl_coro_id = Intrinsic::getDeclaration(TheModule.get(), Intrinsic::coro_id);
Function *decl_coro_begin = Intrinsic::getDeclaration(TheModule.get(), Intrinsic::coro_begin);

// create example function
std::vector<Type *> args;
FunctionType *FT =
    FunctionType::get(Type::getVoidTy(*TheContext), args, false);
Function *F =
    Function::Create(FT, Function::ExternalLinkage, name, TheModule.get());

BasicBlock* bb = BasicBlock::Create(*TheContext, "entry", F);
Builder->SetInsertPoint(bb);

// Get the coro token
std::vector<Value *> argsV;
argsV.push_back(ConstantInt::get(*TheContext, APInt(32, 0, true)));
PointerType* pty = PointerType::getInt8PtrTy(*TheContext);
auto cpn = ConstantPointerNull::get(pty);
argsV.push_back(cpn);
argsV.push_back(cpn);
argsV.push_back(cpn);
Value* val_coro_id = Builder->CreateCall(decl_coro_id, argsV, "id");

// Get the coro size
Value* val_coro_size = Builder->CreateCall(decl_coro_size, None, "size");

// Allocate space
Type* ity = Type::getInt32Ty(*TheContext);
Type* ty = Type::getInt8Ty(*TheContext);
Instruction* call_malloc = CallInst::CreateMalloc(bb, ity, ty, val_coro_size, nullptr, nullptr, "");
Value* val_alloc = Builder->Insert(call_malloc, "alloc");

// Begin coroutine
std::vector<Value *> beginArgs;
beginArgs.push_back(val_coro_id);
beginArgs.push_back(val_alloc);
Value* val_coro_begin = Builder->CreateCall(decl_coro_begin, beginArgs, "hdl");

Builder->CreateRetVoid();

推荐答案

在尝试协同程序时,我遇到了同样的事情.

I hit the same thing when experimenting with coroutines.

可能有一种更简单的方法,但是我通过在此处

There might be a simpler way, but I solved it by building on the module optimization passes described here

  llvm::PipelineTuningOptions pto;
  pto.Coroutines = true;  // <<<<<<<<<<<<<<<<
  llvm::PassBuilder passBuilder(/*DebugLogging=*/true,
    /*TargetMachine=*/nullptr, pto);
  // ...
  llvm::ModulePassManager modulePassManager =
    passBuilder.buildPerModuleDefaultPipeline(olevel);
  modulePassManager.run(*Module, moduleAnalysisManager);

这篇关于LLVM 错误无法选择内部 %llvm.coro.begin的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆