コンパイラの実装に関するLLVMチュートリアルに従っていますが、オブジェクトコードを発行しようとすると、私のコードはsegfaultsになります。オブジェクトコードを発行しようとすると、なぜLLVMがsegfaultするのですか?
ここに、関数func
をコンパイルしようとする最小限の例があります。物事を単純にするために、func
は何もしない関数です。
#include <iostream>
#include <llvm/ADT/Optional.h>
#include <llvm/IR/BasicBlock.h>
#include <llvm/IR/DerivedTypes.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/LegacyPassManager.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/Type.h>
#include <llvm/IR/Verifier.h>
#include <llvm/Support/CodeGen.h>
#include <llvm/Support/FileSystem.h>
#include <llvm/Support/Host.h>
#include <llvm/Support/TargetRegistry.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/Support/raw_ostream.h>
#include <llvm/Target/TargetMachine.h>
#include <llvm/Target/TargetOptions.h>
#include <stdexcept>
#include <string>
#include <system_error>
#include <vector>
int main() {
llvm::LLVMContext context;
llvm::IRBuilder<> builder(context);
llvm::Module module("module", context);
llvm::Function* const func = llvm::Function::Create(
llvm::FunctionType::get(llvm::Type::getVoidTy(context),
std::vector<llvm::Type*>(), false),
llvm::Function::ExternalLinkage, "func", &module
);
builder.SetInsertPoint(llvm::BasicBlock::Create(context, "entry", func));
llvm::verifyFunction(*func);
func->dump();
llvm::InitializeAllTargetInfos();
llvm::InitializeAllTargets();
llvm::InitializeAllTargetMCs();
llvm::InitializeAllAsmParsers();
llvm::InitializeAllAsmPrinters();
const std::string triple = llvm::sys::getDefaultTargetTriple();
std::string message;
const llvm::Target* const target = llvm::TargetRegistry::lookupTarget(
triple, message
);
if (!target) throw std::runtime_error("Couldn't find target.");
llvm::TargetMachine* const machine = target->createTargetMachine(
triple, "generic", "", llvm::TargetOptions(),
llvm::Optional<llvm::Reloc::Model>()
);
module.setDataLayout(machine->createDataLayout());
module.setTargetTriple(triple);
std::error_code code;
llvm::raw_fd_ostream obj_file("func.o", code, llvm::sys::fs::F_None);
if (code) throw std::runtime_error("Couldn't open object file.");
llvm::legacy::PassManager manager;
if (
machine->addPassesToEmitFile(manager, obj_file,
llvm::TargetMachine::CGFT_ObjectFile)
) throw std::runtime_error("Adding passes failed.");
std::cout << "Running pass manager." << std::endl;
manager.run(module);
std::cout << "Ran pass manager." << std::endl;
obj_file.flush();
}
ここではコンパイルするコマンドを示します。私はGCCバージョン6.3.1とLLVMバージョン3.9.1を使用しています。
g++ src/main.cc -o bin/test -std=c++1z -Wall -Wextra \
-Wno-unused-function -Wno-unused-value -Wno-unused-parameter \
-Werror -ggdb -O0 `llvm-config --system-libs --libs core`
出力は次のとおりです。
define void @func() {
entry:
}
Running pass manager.
Segmentation fault (core dumped)
IRへの翻訳が成功する - 少なくとも私にはダンプが正しく見える - しかし、セグメンテーションフォルトがllvm::legacy::PassManager::run
を呼んで発生します。
GDBでコードを実行してみました。ここでは、セグメンテーションの瞬間からのバックトレースがあります。
#0 0x00007ffff56ce72f in ??() from /usr/lib/libLLVM-3.9.so
#1 0x00007ffff56477c2 in llvm::FPPassManager::runOnFunction(llvm::Function&)() from /usr/lib/libLLVM-3.9.so
#2 0x00007ffff5647b4b in llvm::FPPassManager::runOnModule(llvm::Module&)() from /usr/lib/libLLVM-3.9.so
#3 0x00007ffff5647e74 in llvm::legacy::PassManagerImpl::run(llvm::Module&)() from /usr/lib/libLLVM-3.9.so
#4 0x0000000000403ab6 in main() at src/main.cc:76
残念ながら、(アーチLinux上pacman
を使用してインストール)私のLLVMのインストールは行番号デバッグ情報を持っていないようですので、私はllvm::FPPassManager::runOnFunction
の実行中に問題が発生している場所を正確に伝えることができません。
私は何をしようとしているのか、コンセプトかインプリメンテーションのどちらかに間違いがありますか?
はそれを解決しました。ありがとう!私は関数が 'void'だったからといって' return'ステートメントが必要ではないと仮定してはなりませんでした。うわー。他のヒントも参考になります。 –