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 on Compilation of Tuple of Unions #1513

Closed
SeanTAllen opened this issue Jan 11, 2017 · 11 comments · Fixed by #2176
Closed

Segfault on Compilation of Tuple of Unions #1513

SeanTAllen opened this issue Jan 11, 2017 · 11 comments · Fixed by #2176
Assignees
Labels
triggers release Major issue that when fixed, results in an "emergency" release

Comments

@SeanTAllen
Copy link
Member

SeanTAllen commented Jan 11, 2017

primitive Add
primitive Dec
type AddOrDec is (Add | Dec)
type CmRDTCounterOp is (AddOrDec, U128)

class CmRDTCounter
  var _value: U128

  new create() => _value = 0

  fun read(): U128 =>
    _value

  fun ref add(number: U128): CmRDTCounterOp =>
    let op: CmRDTCounterOp =
      if number >= 0 then
        (Add, number)
      else
        (Dec, number)
      end
    apply(op)
    op

  fun ref apply(op: CmRDTCounterOp) =>
    match op
      | (Add, let number: U128) => _value = _value + number
      | (Dec, let number: U128) => _value = _value - number
    end

actor Main
  new create(env: Env) =>
    var counter = CmRDTCounter.create()
    let op1 = counter.add(10)

The last line causes the segfault. Remove it and all is good.

I built using latest master. LLVM 3.9.1. OSX.

Was first reported by omarkj on IRC.

Backtrace under LLDB:

* thread #1: tid = 0x1a9dea, 0x0000000100b8509f ponyc`llvm::Value::setNameImpl(llvm::Twine const&) + 31, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
  * frame #0: 0x0000000100b8509f ponyc`llvm::Value::setNameImpl(llvm::Twine const&) + 31
    frame #1: 0x0000000100b8533c ponyc`llvm::Value::setName(llvm::Twine const&) + 14
    frame #2: 0x0000000100836cfc ponyc`llvm::ExtractValueInst::Create(llvm::Value*, llvm::ArrayRef<unsigned int>, llvm::Twine const&, llvm::Instruction*) + 140
    frame #3: 0x0000000100b22809 ponyc`llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>::CreateExtractValue(llvm::Value*, llvm::ArrayRef<unsigned int>, llvm::Twine const&) + 89
    frame #4: 0x0000000100b227a9 ponyc`LLVMBuildExtractValue + 49
    frame #5: 0x0000000100c3dd08 ponyc`gen_assign_cast + 936
    frame #6: 0x0000000100c423db ponyc`assign_rvalue + 651
    frame #7: 0x0000000100c3a504 ponyc`gen_expr + 12676
    frame #8: 0x0000000100c38eb8 ponyc`gen_expr + 6968
    frame #9: 0x0000000100c55f4a ponyc`gentypes + 28794
    frame #10: 0x0000000100c31ac4 ponyc`codegen + 12164
    frame #11: 0x0000000100c047c4 ponyc`main + 6548
    frame #12: 0x00007fff9f1645ad libdyld.dylib`start + 1
    frame #13: 0x00007fff9f1645ad libdyld.dylib`start + 1
@SeanTAllen SeanTAllen added bug: 1 - needs investigation triggers release Major issue that when fixed, results in an "emergency" release labels Jan 11, 2017
@omarkj
Copy link

omarkj commented Jan 11, 2017

Compiler details:

0.10.0 [release]
compiled with: llvm 3.9.0 -- Apple LLVM version 8.0.0 (clang-800.0.42.1)

I also ran this against current ponyc master (c223fc4). Backtrace under LLDB with that build:

* thread #1: tid = 0x2e1058, 0x0000000101843dd6 libsystem_kernel.dylib`__pthread_kill + 10, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
  * frame #0: 0x0000000101843dd6 libsystem_kernel.dylib`__pthread_kill + 10
    frame #1: 0x000000010199a787 libsystem_pthread.dylib`pthread_kill + 90
    frame #2: 0x0000000100b959fd ponyc`abort + 14
    frame #3: 0x0000000100b959ef ponyc`__assert_rtn + 81
    frame #4: 0x000000010004517e ponyc`gen_assign_cast(c=0x00007fff5fbff350, l_type=0x000000010b800d30, r_value=0x0000000101d05e78, type=0x000000011122f380) + 526 at genexpr.c:287
    frame #5: 0x000000010003986a ponyc`gen_call(c=0x00007fff5fbff350, ast=0x000000011122da80) + 2778 at gencall.c:687
    frame #6: 0x00000001000448db ponyc`gen_expr(c=0x00007fff5fbff350, ast=0x000000011122da80) + 379 at genexpr.c:80
    frame #7: 0x000000010003c304 ponyc`gen_seq(c=0x00007fff5fbff350, ast=0x000000011121a280) + 84 at gencontrol.c:19
    frame #8: 0x00000001000447d9 ponyc`gen_expr(c=0x00007fff5fbff350, ast=0x000000011121a280) + 121 at genexpr.c:25
    frame #9: 0x0000000100046a05 ponyc`genfun_fun(c=0x00007fff5fbff350, t=0x0000000111231800, m=0x0000000111231b00) + 293 at genfun.c:298
    frame #10: 0x0000000100045dc9 ponyc`genfun_method_bodies(c=0x00007fff5fbff350, t=0x0000000111231800) + 441 at genfun.c:706
    frame #11: 0x0000000100066cee ponyc`gentypes(c=0x00007fff5fbff350) + 846 at gentype.c:779
    frame #12: 0x0000000100043824 ponyc`genexe(c=0x00007fff5fbff350, program=0x000000010afdf000) + 484 at genexe.c:434
    frame #13: 0x000000010003582a ponyc`codegen(program=0x000000010afdf000, opt=0x00007fff5fbff778) + 234 at codegen.c:904
    frame #14: 0x0000000100091213 ponyc`generate_passes(program=0x000000010afdf000, options=0x00007fff5fbff778) + 51 at pass.c:291
    frame #15: 0x0000000100001791 ponyc`compile_package(path=".", opt=0x00007fff5fbff778, print_program_ast=false, print_package_ast=false) + 161 at main.c:247
    frame #16: 0x0000000100001548 ponyc`main(argc=1, argv=0x00007fff5fbff828) + 1112 at main.c:370
    frame #17: 0x0000000101695255 libdyld.dylib`start + 1
    frame #18: 0x0000000101695255 libdyld.dylib`start + 1

Additionally, that compiler returns some more information during the fault:

Building builtin -> /Users/omarkj/code/ponyc/packages/builtin
Building . -> /Users/omarkj/code/bogi/src
Generating
 Reachability
 Selector painting
 Data prototypes
 Data types
 Function prototypes
 Functions
Assertion failed: (LLVMGetTypeKind(LLVMTypeOf(r_value)) == LLVMStructTypeKind), function gen_assign_cast, file src/libponyc/codegen/genexpr.c, line 287.

@omarkj
Copy link

omarkj commented Jan 14, 2017

Hey,

Been looking into this issue some more, and have narrowed it down to the return from the if statement which is bound using let. If I instead write this code things compile:

  fun ref makeOperation(number: U128) =>
    if number >= 0 then
      apply((Add, number))
    else
      apply((Dec, number))
    end

To get the other path (that is, returning from the if statement, binding it and passing it to another function) working I need to handle the impossible case that the if statement does not return by wrapping the return in a Maybe and guard against it later:

First I added these types:

primitive Nothing is Stringable
  fun string(): String iso^ => "Nothing".string()
type Maybe[A] is (Nothing | A)

And then rewrite the logic this way:

  fun ref maybeMakeAndApplyOperation(number: U128): Maybe[U128] =>
    let maybeOp =
      if number >= 0 then
        (Add, number)
      else
        (Dec, number)
      end
    maybeApply(maybeOp)

  fun ref maybeApply(op: Maybe[CmRDTCounterOp]): Maybe[U128] =>
    match op
      | Nothing => Nothing
      | (let o: CmRDTCounterOp) => _apply(o)
    else
      Nothing
    end

This compiles and runs as expected.

@omarkj
Copy link

omarkj commented Jan 14, 2017

I've been looking into this a little bit, and isolated this to the primitive that's in
the boxed type. gen_unbox in genbox.c on line 45 returns the unchanged object if
t->primitive is NULL which happens to be the case here.

Is probably related to the reachability ds, similar to #1474.

@SeanTAllen
Copy link
Member Author

@omarkj awesome digging

@Praetonus
Copy link
Member

This probably is another case of the general issue with tuples not having a type descriptor.

@SeanTAllen
Copy link
Member Author

@sylvanc doesn't believe this is tuples related. going to be looking at it. i'm leaving the needs discussion during sync tag so we revisit next week.

@SeanTAllen
Copy link
Member Author

This now errors at:

src/libponyc/codegen/genexpr.c:306: gen_assign_cast: Assertion `LLVMGetTypeKind(LLVMTypeOf(r_value)) == LLVMStructTypeKind` failed.

Backtrace:
  0   ponyc                               0x000000010401f8d1 ponyint_assert_fail + 161
  1   ponyc                               0x0000000103f8750f gen_assign_cast + 927
  2   ponyc                               0x0000000103f951d1 assign_rvalue + 801
  3   ponyc                               0x0000000103f94e34 gen_assign + 180
  4   ponyc                               0x0000000103f86994 gen_expr + 260
  5   ponyc                               0x0000000103f80a64 gen_seq + 68
  6   ponyc                               0x0000000103f86c42 gen_expr + 946
  7   ponyc                               0x0000000103f89901 genfun_method_bodies + 3153
  8   ponyc                               0x0000000103faca30 gentypes + 6464
  9   ponyc                               0x0000000103f86444 genexe + 596
  10  ponyc                               0x0000000103f78b57 codegen + 199
  11  ponyc                               0x0000000103f44a25 main + 1557
  12  libdyld.dylib                       0x00007fff93ae45ad start + 1

@SeanTAllen
Copy link
Member Author

backtrace:

(lldb) bt
* thread #1: tid = 0x8836ee, 0x00007fff99300f06 libsystem_kernel.dylib`__pthread_kill + 10, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
  * frame #0: 0x00007fff99300f06 libsystem_kernel.dylib`__pthread_kill + 10
    frame #1: 0x00007fff93c4a4ec libsystem_pthread.dylib`pthread_kill + 90
    frame #2: 0x00007fff98c166df libsystem_c.dylib`abort + 129
    frame #3: 0x00000001000fb223 ponyc`ponyint_assert_fail(expr="LLVMGetTypeKind(LLVMTypeOf(r_value)) == LLVMStructTypeKind", file="src/libponyc/codegen/genexpr.c", line=306, func="gen_assign_cast") + 403 at ponyassert.c:60
    frame #4: 0x000000010004afda ponyc`gen_assign_cast(c=0x00007fff5fbff268, l_type=0x000000010b803e10, r_value=0x000000010c204718, type=0x0000000108024700) + 634 at genexpr.c:306
    frame #5: 0x00000001000576a5 ponyc`assign_local(c=0x00007fff5fbff268, l_value=0x000000010c2047e8, r_value=0x000000010c204718, l_type=0x0000000108044080, r_type=0x0000000108024700) + 149 at genoperator.c:334
    frame #6: 0x0000000100057396 ponyc`assign_rvalue(c=0x00007fff5fbff268, left=0x0000000108025180, r_type=0x0000000108024700, r_value=0x000000010c204718) + 1174 at genoperator.c:519
    frame #7: 0x000000010005714c ponyc`assign_rvalue(c=0x00007fff5fbff268, left=0x0000000108054e40, r_type=0x0000000108024700, r_value=0x000000010c204718) + 588 at genoperator.c:445
    frame #8: 0x0000000100056eb3 ponyc`gen_assign(c=0x00007fff5fbff268, ast=0x0000000108057bc0) + 179 at genoperator.c:897
    frame #9: 0x000000010004a835 ponyc`gen_expr(c=0x00007fff5fbff268, ast=0x0000000108057bc0) + 821 at genexpr.c:144
    frame #10: 0x0000000100041c04 ponyc`gen_seq(c=0x00007fff5fbff268, ast=0x000000010804ecc0) + 84 at gencontrol.c:22
    frame #11: 0x000000010004a579 ponyc`gen_expr(c=0x00007fff5fbff268, ast=0x000000010804ecc0) + 121 at genexpr.c:25
    frame #12: 0x000000010004cda1 ponyc`genfun_fun(c=0x00007fff5fbff268, t=0x0000000107fe7200, m=0x0000000107fe5c00) + 529 at genfun.c:436
    frame #13: 0x000000010004c039 ponyc`genfun_method_bodies(c=0x00007fff5fbff268, t=0x0000000107fe7200) + 441 at genfun.c:895
    frame #14: 0x000000010007a943 ponyc`gentypes(c=0x00007fff5fbff268) + 979 at gentype.c:884
    frame #15: 0x0000000100049f68 ponyc`genexe(c=0x00007fff5fbff268, program=0x000000010afbfd40) + 504 at genexe.c:409
    frame #16: 0x0000000100039a42 ponyc`codegen(program=0x000000010afbfd40, opt=0x00007fff5fbff768) + 274 at codegen.c:1026
    frame #17: 0x00000001000a8dd3 ponyc`generate_passes(program=0x000000010afbfd40, options=0x00007fff5fbff768) + 51 at pass.c:301
    frame #18: 0x0000000100002691 ponyc`compile_package(path=".", opt=0x00007fff5fbff768, print_program_ast=false, print_package_ast=false) + 161 at main.c:255
    frame #19: 0x000000010000243a ponyc`main(argc=1, argv=0x00007fff5fbff818) + 1146 at main.c:395
    frame #20: 0x00007fff93ae45ad libdyld.dylib`start + 1
    frame #21: 0x00007fff93ae45ad libdyld.dylib`start + 1

@sylvanc
Copy link
Contributor

sylvanc commented Aug 16, 2017

@Praetonus was exactly right. It's a union of tuples vs tuples of unions problem.

@sylvanc
Copy link
Contributor

sylvanc commented Aug 16, 2017

On line 305 in genexpr.c, the compiler is expecting to find that the RHS is a boxed tuple type, since the LHS is a tuple type. Instead, it finds that the RHS is a union of two tuple types. As a result, the compiler has no c_t->primitive to unbox with. It's possible the right approach is to use the type descriptor in a boxed tuple to figure out how to unbox it.

@jemc jemc changed the title Segfault on Compilation Segfault on Compilation of Tuple of Unions Aug 16, 2017
@Praetonus Praetonus self-assigned this Aug 17, 2017
@Praetonus
Copy link
Member

Minimal case:

actor Main
  new create(env: Env) =>
    let a: ((Main, Env) | (Env, Main)) = (this, env)
    let b: ((Main | Env), (Main | Env)) = a

Praetonus pushed a commit to Praetonus/ponyc that referenced this issue Aug 17, 2017
This change fixes a compiler crash when converting a union of tuples to
a tuple.

Closes ponylang#1513.
SeanTAllen pushed a commit that referenced this issue Aug 19, 2017
This change fixes a compiler crash when converting a union of tuples to
a tuple.

Closes #1513.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
triggers release Major issue that when fixed, results in an "emergency" release
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants