ponyc
ponyc copied to clipboard
ponyc Segmentation Fault (core dumped) when given broken code.
While trying to understand error messages and precedence I may have triggered a compiler bug. I completely did it myself so please feel free to just close it if it is not useful.
The root error of course is that I'm trying to shr greater than the size of the datastructure. The error for that is straightforward.
When I try to print the result, I get the expected argument not subtype of parameter.
When I try to call string() on the expression which is illegal - the compiler core dumps.
actor Main
new create(env: Env) =>
let y: U32 val = 1
// let y31: U32 val = y.shr(32) // (compile fail) shift amount greater than type width
// let unk = y.shr(32) // (compile fail) shift amount greater than type width
// env.out.print(y.shr(32)) // (compile fail) argument not a subtype of parameter
env.out.print(y.shr(33).string()) // Compiler Dumps Core
Error:
[nix-shell:~/projects/pony/notjs]$ ponyc .
Building builtin -> /nix/store/i31sdrkcnjsxaw1fn98mdmnglnrm9z87-ponyc-0.31.0/lib/pony/0.31.0/packages/builtin
Building . -> /home/red/projects/pony/notjs
Generating
Reachability
Selector painting
Data prototypes
Data types
Function prototypes
Functions
Descriptors
Optimising
Stack dump:
0. Running pass 'Interprocedural Sparse Conditional Constant Propagation' on module 'notjs'.
Segmentation fault (core dumped)
I had a friend on (not)NixOS confirm too.
(like I said - self inflicted)
Pony version:
0.31.0 [release]
compiled with: llvm 7.1.0 -- gcc (GCC) 8.3.0
Defaults: pic=false
I'm compiling 0.32.0 to test too...
@redvers can you run ponyc --version
and add the output to your report? Thanks.
Done above - also - I installed 0.32.0 too with the same result:
0.32.0 [release]
compiled with: llvm 7.1.0 -- gcc (GCC) 8.3.0
Defaults: pic=false
Red
Thanks for the detailed issue ticket!
As you show, there is an edge case of some kind in which the compiler's logic for statically checking the number of bits to shift against the type width, so that this check isn't happening as it should, or isn't happening correctly, when it is specified inline with the .string()
suffix.
That is, when we generate LLVM code for the shr
method, we have two approaches for doing so:
- if the number of bits is a constant value (like an integer literal), we check it against the type width at compile time and issue a compile error if warranted (the "shift amount greater than type width" error mentioned above)
- otherwise, the number of bits is not known at compile time and must be checked at runtime, so we generate slightly slower code that will check the number of bits at runtime before shifting, so that it is clamped to be at most equal to the maximum value we allow.
See the code here: https://github.com/ponylang/ponyc/blob/70d471d2394c8c3c6f6e952b70f69e19db9f0569/src/libponyc/codegen/genoperator.c#L727-L786
Obviously, since it is a literal integer we expect it to take the first path here and catch the issue at compile time, but for some reason in this edge case it is not. I suspect that is resulting in an LLVM undef
or poison
value being generated as the result, breaking later LLVM optimizations.
Since I'm familiar with this part of the code I'll assign myself and try to take a look at this soon.
@jemc should we remove you from this issue and add "help wanted"?
Yes, I'll un-assign myself, but if anyone wants help understanding the LLVM code gen stuff in this area of the compiler I'd be happy to assist in that way.