llvm - CompileLayerT::addModule 无故崩溃
问题描述
我正在尝试在我的代码中创建一个 llvm JIT:
#include <iostream>
#include <vector>
#include <memory>
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/Verifier.h"
#include "KaleidoscopeJIT.h"
#include "llvm/Support/TargetSelect.h"
int main() {
llvm::InitializeNativeTarget();
llvm::InitializeNativeTargetAsmPrinter();
llvm::InitializeNativeTargetAsmParser();
llvm::LLVMContext context;
llvm::orc::KaleidoscopeJIT jit;
auto module = std::make_unique<llvm::Module>("top", context);
llvm::IRBuilder<> builder(context);
module->setDataLayout(jit.getTargetMachine().createDataLayout());
llvm::FunctionType *funcType = llvm::FunctionType::get(builder.getVoidTy(), false);
llvm::Function *mainFunc =
llvm::Function::Create(funcType, llvm::Function::ExternalLinkage, "main", module.get());
llvm::BasicBlock *entry = llvm::BasicBlock::Create(context, "", mainFunc);
builder.SetInsertPoint(entry);
module->print(llvm::errs(), nullptr);
auto H = jit.addModule(std::move(module));
...
...
}
当谈到 时addModule
,程序崩溃(被信号 11:SIGSEGV 中断),我调试了堆栈:
llvm::Instruction::getNumSuccessors() const 0x0000565102dbd7e0
llvm::BranchProbabilityInfo::updatePostDominatedByUnreachable(llvm::BasicBlock const*) 0x000056510361d797
llvm::BranchProbabilityInfo::calculate(llvm::Function const&, llvm::LoopInfo const&, llvm::TargetLibraryInfo const*) 0x00005651036220ef
llvm::BranchProbabilityInfoWrapperPass::runOnFunction(llvm::Function&) 0x00005651036225bd
llvm::FPPassManager::runOnFunction(llvm::Function&) 0x0000565102ddc640
llvm::FPPassManager::runOnModule(llvm::Module&) 0x0000565102ddc8b3
llvm::legacy::PassManagerImpl::run(llvm::Module&) 0x0000565102ddcc7e
llvm::orc::SimpleCompiler::operator() CompileUtils.h:68
llvm::orc::LegacyIRCompileLayer<llvm::orc::LegacyRTDyldObjectLinkingLayer, llvm::orc::SimpleCompiler>::addModule IRCompileLayer.h:84
llvm::orc::KaleidoscopeJIT::addModule KaleidoscopeJIT.h:66
main main.cpp:34
__libc_start_main 0x00007f8d8ee38b97
_start 0x0000565102cdc1ca
万花筒JIT.h:
//===- KaleidoscopeJIT.h - A simple JIT for Kaleidoscope --------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Contains a simple JIT definition for use in the kaleidoscope tutorials.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H
#define LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Mangler.h"
#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include <algorithm>
#include <map>
#include <memory>
#include <string>
#include <vector>
namespace llvm {
namespace orc {
class KaleidoscopeJIT {
public:
using ObjLayerT = LegacyRTDyldObjectLinkingLayer;
using CompileLayerT = LegacyIRCompileLayer<ObjLayerT, SimpleCompiler>;
KaleidoscopeJIT()
: Resolver(createLegacyLookupResolver(
ES,
[this](const std::string &Name) {
return ObjectLayer.findSymbol(Name, true);
},
[](Error Err) { cantFail(std::move(Err), "lookupFlags failed"); })),
TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()),
ObjectLayer(ES,
[this](VModuleKey) {
return ObjLayerT::Resources{
std::make_shared<SectionMemoryManager>(), Resolver};
}),
CompileLayer(ObjectLayer, SimpleCompiler(*TM)) {
llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr);
}
TargetMachine &getTargetMachine() { return *TM; }
VModuleKey addModule(std::unique_ptr<Module> M) {
auto K = ES.allocateVModule();
cantFail(CompileLayer.addModule(K, std::move(M)));
ModuleKeys.push_back(K);
return K;
}
void removeModule(VModuleKey K) {
ModuleKeys.erase(find(ModuleKeys, K));
cantFail(CompileLayer.removeModule(K));
}
JITSymbol findSymbol(const std::string Name) {
return findMangledSymbol(mangle(Name));
}
private:
std::string mangle(const std::string &Name) {
std::string MangledName;
{
raw_string_ostream MangledNameStream(MangledName);
Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
}
return MangledName;
}
JITSymbol findMangledSymbol(const std::string &Name) {
#ifdef _WIN32
// The symbol lookup of ObjectLinkingLayer uses the SymbolRef::SF_Exported
// flag to decide whether a symbol will be visible or not, when we call
// IRCompileLayer::findSymbolIn with ExportedSymbolsOnly set to true.
//
// But for Windows COFF objects, this flag is currently never set.
// For a potential solution see: https://reviews.llvm.org/rL258665
// For now, we allow non-exported symbols on Windows as a workaround.
const bool ExportedSymbolsOnly = false;
#else
const bool ExportedSymbolsOnly = true;
#endif
// Search modules in reverse order: from last added to first added.
// This is the opposite of the usual search order for dlsym, but makes more
// sense in a REPL where we want to bind to the newest available definition.
for (auto H : make_range(ModuleKeys.rbegin(), ModuleKeys.rend()))
if (auto Sym = CompileLayer.findSymbolIn(H, Name, ExportedSymbolsOnly))
return Sym;
// If we can't find the symbol in the JIT, try looking in the host process.
if (auto SymAddr = RTDyldMemoryManager::getSymbolAddressInProcess(Name))
return JITSymbol(SymAddr, JITSymbolFlags::Exported);
#ifdef _WIN32
// For Windows retry without "_" at beginning, as RTDyldMemoryManager uses
// GetProcAddress and standard libraries like msvcrt.dll use names
// with and without "_" (for example "_itoa" but "sin").
if (Name.length() > 2 && Name[0] == '_')
if (auto SymAddr =
RTDyldMemoryManager::getSymbolAddressInProcess(Name.substr(1)))
return JITSymbol(SymAddr, JITSymbolFlags::Exported);
#endif
return nullptr;
}
ExecutionSession ES;
std::shared_ptr<SymbolResolver> Resolver;
std::unique_ptr<TargetMachine> TM;
const DataLayout DL;
ObjLayerT ObjectLayer;
CompileLayerT CompileLayer;
std::vector<VModuleKey> ModuleKeys;
};
} // end namespace orc
} // end namespace llvm
#endif // LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H
但是如果我在https://llvm.org/docs/tutorial/MyFirstLanguageFrontend/LangImpl04.html中运行代码,它运行良好,所以我猜环境是对的。
知道为什么它崩溃了吗?
解决方案
AlexDenisov 的评论是正确的:BasicBlocks 应该以终止指令结束。尝试添加
builder.CreateRetVoid();
在调用builder.setInsertPoint
和之间添加到您的代码module->print
。
推荐阅读
- python-3.x - 列表中的一对坐标,其 y 轴相等且 x 轴彼此大或小 1
- autodesk-forge - BIM 360 无法创建现有文件的版本
- r - 多项式回归图 R
- javascript - 无法读取未定义状态图像的属性“调整大小”?
- xml - PowerShell / XML - 根据节点值将 xml 文件复制到文件夹
- swi-prolog - 在 Prolog 中打印二叉树
- node.js - 如何在带有 Nodist 的 VS Code 命令行中使用 Node?(视窗 10)
- linux - Gnuplot:在 splot 上绘制 x、y 和 z 值
- javascript - setInterval 和 clearInterval 不能一起工作
- vue.js - 观察对象数组内的数组