Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Module::write_bitcode_to_path causing segfault #555

Open
cyccro opened this issue Dec 4, 2024 · 3 comments
Open

Module::write_bitcode_to_path causing segfault #555

cyccro opened this issue Dec 4, 2024 · 3 comments
Labels

Comments

@cyccro
Copy link

cyccro commented Dec 4, 2024

While trying to write the bitcode to the given path, it causes sigfault. I don't understand why because before I added some changes it was working correctly. I tried debugging it and the call stack that appears in vscode is the following:

(anonymous namespace)::ModuleBitcodeWriter::pushValueAndType(llvm::Value const*, unsigned int, llvm::SmallVectorImpl&)
(@(anonymous namespace)::ModuleBitcodeWriter::pushValueAndType(llvm::Value const*, unsigned int, llvm::SmallVectorImpl&):35)
(anonymous namespace)::ModuleBitcodeWriter::writeInstruction(llvm::Instruction const&, unsigned int, llvm::SmallVectorImpl&)
(@(anonymous namespace)::ModuleBitcodeWriter::writeInstruction(llvm::Instruction const&, unsigned int, llvm::SmallVectorImpl&):3651)
(anonymous namespace)::ModuleBitcodeWriter::write()
(@(anonymous namespace)::ModuleBitcodeWriter::write():3818)
llvm::BitcodeWriter::writeModule(llvm::Module const&, bool, llvm::ModuleSummaryIndex const*, bool, std::array<unsigned int, 5ul>)
(@llvm::BitcodeWriter::writeModule(llvm::Module const&, bool, llvm::ModuleSummaryIndex const
, bool, std::array<unsigned int, 5ul>):108)
llvm::WriteBitcodeToFile(llvm::Module const&, llvm::raw_ostream&, bool,llvm::ModuleSummaryIndex const
, bool, std::array<unsigned int, 5ul>) (@llvm::WriteBitcodeToFile(llvm::Module const&, llvm::raw_ostream&, bool, llvm::ModuleSummaryIndex const, bool, std::array<unsigned int, 5ul>*):64)
LLVMWriteBitcodeToFile (@LLVMWriteBitcodeToFile:35)
inkwell::module::Module::write_bitcode_to_path (/.cargo/registry/src/index.crates.io-6f17d22bba15001f/inkwell-0.5.0/src/module.rs:674)
compiler::CodeGenerator::compile_ast (
/Programmation/hdc/compiler/src/lib.rs:60)
compiler::compile_ast (/Programmation/hdc/compiler/src/lib.rs:68)
compiler::compile_from_to (
/Programmation/hdc/compiler/src/lib.rs:75)
hdc::main (~/Programmation/hdc/src/main.rs:36)
... the rest is rust internals

I really have no idea of how to solve this problem.

OS: Linux Mint 21.3
LLVM version: 14.0.0

@TheDan64 TheDan64 changed the title Module::write_bitcode_to_path causing sigfault Module::write_bitcode_to_path causing segfault Dec 11, 2024
@TheDan64 TheDan64 added the bug label Dec 19, 2024
@bfbachmann
Copy link

bfbachmann commented Dec 31, 2024

@cyccro do you have code that you can link? I've noticed something similar myself.

I have a test that I run using cargo test that locates, compiles, and runs a whole bunch of programs. Essentially, the test is finding all my "test programs", compiling them (using Inkwell), and then running them all as separate child processes and checking that they exit with code 0.

This worked perfectly all the time, right up until I introduced this code to my backend

    // Run optimization passes.
    let opts = PassBuilderOptions::create();
    opts.set_verify_each(true);

    let opt_level = match config.optimization_level {
        OptimizationLevel::None => "default<O0>",
        OptimizationLevel::Less => "default<O1>",
        OptimizationLevel::Default => "default<O2>",
        OptimizationLevel::Aggressive => "default<O3>",
    };
    module
        .run_passes(opt_level, config.target_machine, opts)
        .expect("should succeed");

Since that point, it seems like I get the same segfault, but only if my test compiles and runs more than 15 test programs. Any less and it works fine! In other words, the segfault will only happen if I run the full compilation pipeline (including the code I pasted above), more than 15 times in the same process.

@bfbachmann
Copy link

bfbachmann commented Jan 1, 2025

It also seems like any time I try to use the PassManagerBuilder (following the example from populate_function_pass_manager), it also causes a similar panic. Again, this only happens when I try to run the full compilation pipeline more than once. Running just once always works fine.

@bfbachmann
Copy link

bfbachmann commented Jan 2, 2025

@cyccro Ok, I think I've figured out what's going on, at least in my case. Hopefully some of this info will be of use to you, even if my case isn't identical to yours.

Just before LLVM goes to write your bitcode to a file, it's going to try to run some passes over your IR. Some of this might be to verify your IR, or to optimize it, or maybe something else - I'm not sure. Anyway, I think these passes make certain assumptions about the validity of your IR which, if violated, may cause LLVM to segfault. I was able to diagnose these issues by doing the following:

  1. Turn off ALL LLVM optimization passes, if you're using any. In other words, make sure there is absolutely no transformation happening on your IR before it gets written to a file.
  2. Instead of writing bitcode to a file, write IR to the file (module.print_to_file(path)).
  3. Use the LLVM opt CLI to verify your raw IR: the command for this should look something like opt --passes=lint,verify "$YOUR_IR_FILE" -o /dev/null. opt should print out errors for any IR you have generated that is invalid.

If, like me, you have invalid IR, try finding and fixing the causes of that invalid IR in your compiler, then see if that fixes your segfault problems. It's worth noting that, for some reason, module.verify() and func.verify() don't seem to actually catch all cases of invalid IR that opt catches.

You could also try doing the inverse: generate some extremely trivial valid IR with your compiler and check that it doesn't segfault. If it doesn't segfault on trivially valid IR, then the cause of the segfault might really be invalid IR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants