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

Segfault in 'Simplify the CFG' pass when discarding a capture in a match inside a loop #2767

Closed
burjui opened this issue Jun 8, 2018 · 8 comments
Assignees
Labels
needs investigation This needs to be looked into before its "ready for work" triggers release Major issue that when fixed, results in an "emergency" release

Comments

@burjui
Copy link

burjui commented Jun 8, 2018

actor Main
  new create(env: Env) =>
    let x: (None | U8) = 1
    while true do
      let _: None = match x
        | let _: U8 => None
      end
    end

This causes a segfault on Arch Linux x86_64 with Pony 0.22.6 and on issue-2760 branch:

$ ponyc
...
0.      Running pass 'Simplify the CFG' on function '@Main_tag_create_oo'
[1]    18802 segmentation fault (core dumped)  ponyc

GDB stacktrace:

#0  0x00007ffff4f747c4 in llvm::removeUnreachableBlocks(llvm::Function&, llvm::LazyValueInfo*) () from /usr/lib/libLLVM-6.0.so
#1  0x00007ffff5376dab in ?? () from /usr/lib/libLLVM-6.0.so
#2  0x00007ffff47efdc1 in llvm::FPPassManager::runOnFunction(llvm::Function&) ()
   from /usr/lib/libLLVM-6.0.so
#3  0x00007ffff47efebd in llvm::legacy::FunctionPassManagerImpl::run(llvm::Function&) ()
   from /usr/lib/libLLVM-6.0.so
#4  0x00007ffff47f0405 in llvm::legacy::FunctionPassManager::run(llvm::Function&) ()
   from /usr/lib/libLLVM-6.0.so
#5  0x0000555555611a43 in optimise(compile_t*, bool) ()
#6  0x0000555555611bef in genopt ()
#7  0x000055555560b45f in genexe ()
#8  0x000055555559806d in codegen ()
#9  0x000055555557ba9e in main ()
@SeanTAllen
Copy link
Member

SeanTAllen commented Jun 8, 2018

This goes back to the introduction of _.

This

actor Main
  new create(env: Env) =>
    let x: (None | U8) = 1
    while true do
      let y: None = match x
        | let z: U8 => None
      end
    end

compiles. So this is related to _.

I haven't determined exactly the commit when this happened. It might have always happened. I gave up eventually.

@SeanTAllen SeanTAllen added complexity: requires context triggers release Major issue that when fixed, results in an "emergency" release labels Jun 8, 2018
@dipinhora
Copy link
Contributor

I tried to figure out when this was introduced. It was in #1499 when this syntax was first allowed. Prior to that commit, the syntax wasn't allowed.

Also, the following compiles successfully:

actor Main
  new create(env: Env) =>
    let x: (None | U8) = 1
    while true do
      let y: None = match x
        | let _: U8 => None
      end
    end

However, when compiled without --debug argument to ponyc, it results in an Illegal instruction error when the program is run.

The following also results in the segfault (Running pass 'Simplify the CFG' on function '@Main_tag_create_oo'):

actor Main
  new create(env: Env) =>
    let x: (None | U8) = 1
    while true do
      let _: None = match x
        | let y: U8 => None
      end
    end

Same segfault for this:

actor Main
  new create(env: Env) =>
    while true do
      let _: None = None
    end

However, the following compiles but has the same Illegal Instruction issue:

actor Main
  new create(env: Env) =>
    while true do
      let _: None = None
      let y: None = None
    end

The following also has the same segfault as the original report:

actor Main
  new create(env: Env) =>
    var y: Bool = true
    while y do
      let _: None = None
    end

However, the following compiles and runs successfully:

actor Main
  new create(env: Env) =>
    var y: Bool = true
    while y do
      let _: None = None
      y = false
    end

My guess is that this is related to optimizations that try and remove the while loop altogether because it is an infinite loop with no exit condition.

@burjui
Copy link
Author

burjui commented Jun 11, 2018

Just a note: such an "optimization" would violate the semantics of a program. It is safe to remove code after the infinite loop (with a warning, of course), because it's unreachable, but not the loop itself.

@SeanTAllen
Copy link
Member

@burjui can you clarify what you mean by "remove the code after the infinite loop"?

@Praetonus
Copy link
Member

This is a bug somewhere in genmatch.c where a terminator instruction isn't being generated for a basic block. I'll investigate.

@Praetonus Praetonus self-assigned this Jun 11, 2018
@Praetonus
Copy link
Member

Looks like there's also a type checking bug involved in this.

@burjui
Copy link
Author

burjui commented Jun 11, 2018

@SeanTAllen I mean that if there is some code after an infinite loop, it can be considered unreachable and safe to remove.

@SeanTAllen SeanTAllen added needs investigation This needs to be looked into before its "ready for work" bug and removed bug: 1 - needs investigation labels May 12, 2020
@SeanTAllen
Copy link
Member

I'm no longer able to reproduce this bug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs investigation This needs to be looked into before its "ready for work" triggers release Major issue that when fixed, results in an "emergency" release
Projects
None yet
Development

No branches or pull requests

4 participants