LLVM 错误 Cannot select intrinsic %llvm.coro.begin
LLVM Error Cannot select intrinsic %llvm.coro.begin
我正在学习 LLVM 中的协程功能,并且一直在根据文档中的 examples 之一进行简单测试。
当我尝试 运行 llc
生成的位码时,我收到错误消息 LLVM ERROR: Cannot select: intrinsic %llvm.coro.begin
。到目前为止,我发现的唯一 similar error 是由于某些平台不支持布尔值的 i1
,但是我调用的内在函数 none 使用 i1
.
这是 LLVM IR,我已经删除了调用 llvm.coro.begin
后发生的所有逻辑,以减少发生错误所需的最低限度:
; 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 }
以及生成上述代码的代码:
// 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();
我在尝试协程时遇到了同样的问题。
可能有更简单的方法,但我通过构建
中描述的模块优化过程解决了这个问题
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 中的协程功能,并且一直在根据文档中的 examples 之一进行简单测试。
当我尝试 运行 llc
生成的位码时,我收到错误消息 LLVM ERROR: Cannot select: intrinsic %llvm.coro.begin
。到目前为止,我发现的唯一 similar error 是由于某些平台不支持布尔值的 i1
,但是我调用的内在函数 none 使用 i1
.
这是 LLVM IR,我已经删除了调用 llvm.coro.begin
后发生的所有逻辑,以减少发生错误所需的最低限度:
; 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 }
以及生成上述代码的代码:
// 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();
我在尝试协程时遇到了同样的问题。
可能有更简单的方法,但我通过构建
llvm::PipelineTuningOptions pto;
pto.Coroutines = true; // <<<<<<<<<<<<<<<<
llvm::PassBuilder passBuilder(/*DebugLogging=*/true,
/*TargetMachine=*/nullptr, pto);
// ...
llvm::ModulePassManager modulePassManager =
passBuilder.buildPerModuleDefaultPipeline(olevel);
modulePassManager.run(*Module, moduleAnalysisManager);