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

Compiler crash #910

Closed
Codcore opened this issue Jul 1, 2015 · 2 comments
Closed

Compiler crash #910

Codcore opened this issue Jul 1, 2015 · 2 comments
Labels
kind:bug A bug in the code. Does not apply to documentation, specs, etc. topic:compiler

Comments

@Codcore
Copy link

Codcore commented Jul 1, 2015

I was trying to implement something like a Ruby send method and get compiler crashed:
http://play.crystal-lang.org/#/r/63h

module Sendable

  class WrongNumberOfArguments < Exception
    def initialize(method, given, expected)
      super("Wrong number of arguments for '#{method}' (#{given} for #{expected})")
    end
  end

  class WrongInstanceMethod < Exception
    def initialize(klass, method)
      super("Instance of '#{klass}' class has no '#{method}' method")
    end
  end

  # Allows to invoke objects methods through 'send' method.
  macro create_send
    case method
      {% methods = @type.methods %}
      {% for m in methods %}
      {% args = m.args %}
    when "{{m.name.id}}"
      raise WrongNumberOfArguments.new({{m.name.stringify}}, args.length, {{m.args.length}}) unless args.length == {{m.args.length}}
      {{m.name.id}}{% unless args.empty? %}(
      {% for arg in args %}{{arg.id}}=args[:{{arg.id}}],{% end %}){% end %}
      {% end %}
    else
      raise WrongInstanceMethod.new({{@type.name.stringify}}, "#{method}")
    end
  end

  def send(method, args={} of Symbol => String)
    create_send
  end
end

class My
  include Sendable

  def hello
    send "bye"
  end

  def bye
    bye
  end
end

my = My.new
my.send "hello"

Output

; ModuleID = 'My'

%String = type { i32, i32, i32, i8 }
%My = type { i32 }
%"Hash(Symbol, String)" = type { i32, i32, %"Hash(K, V)::Entry(Symbol, String)"**, i32, i32, i1 }
%"Hash(K, V)::Entry(Symbol, String)" = type { i32 }
%"Sendable::WrongNumberOfArguments" = type { i32, %String*, i1, %"Array(String)"* }
%"Array(String)" = type { i32, i32, i32, %String** }

@symbol_table = external global [1 x %String*]
@str = private constant { i32, i32, i32, [6 x i8] } { i32 1, i32 5, i32 5, [6 x i8] c"hello\00" }
@str1 = private constant { i32, i32, i32, [4 x i8] } { i32 1, i32 3, i32 3, [4 x i8] c"bye\00" }

define %My* @"*My::new:My"() {
alloca:
  %x = alloca %My*
  br label %entry

entry:                                            ; preds = %alloca
  %0 = call i8* @__crystal_malloc(i32 ptrtoint (i32* getelementptr (i32* null, i32 1) to i32))
  %1 = bitcast i8* %0 to %My*
  %2 = bitcast %My* %1 to i8*
  call void @llvm.memset.p0i8.i32(i8* %2, i8 0, i32 ptrtoint (i32* getelementptr (i32* null, i32 1) to i32), i32 4, i1 false)
  %3 = getelementptr inbounds %My* %1, i32 0, i32 0
  store i32 76, i32* %3
  store %My* %1, %My** %x
  %4 = load %My** %x
  %5 = call i1 @"*GC::add_finalizer<My>:Nil"(%My* %4)
  %6 = load %My** %x
  ret %My* %6
}

declare i8* @__crystal_malloc(i32)

; Function Attrs: nounwind
declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1) #0

declare i1 @"*GC::add_finalizer<My>:Nil"(%My*)

; Function Attrs: noreturn
define void @"*My@Sendable#send<My, String>:NoReturn"(%My* %self, %String* %method) #1 {
alloca:

entry:                                            ; No predecessors!
  %0 = call %"Hash(Symbol, String)"* @"*Hash(Symbol, String)::new<Hash(Symbol, String):Class>:Hash(Symbol, String)"(i32 329)
}

declare %"Hash(Symbol, String)"* @"*Hash(Symbol, String)::new<Hash(Symbol, String):Class>:Hash(Symbol, String)"(i32)

; Function Attrs: noreturn
define void @"*My@Sendable#send<My, String, Hash(Symbol, String)>:NoReturn"(%My* %self, %String* %method, %"Hash(Symbol, String)"* %args) #1 {
alloca:

entry:                                            ; No predecessors!
  %0 = call i1 @"*String@Object#===<String, String>:Bool"(%String* bitcast ({ i32, i32, i32, [6 x i8] }* @str to %String*), %String* %method)
  br i1 %0, label %then, label %else

then:                                             ; preds = %entry
  %1 = call i32 @"*Hash(Symbol, String)@Hash(K, V)#length<Hash(Symbol, String)>:Int32"(%"Hash(Symbol, String)"* %args)
  %2 = icmp eq i32 %1, 0
  br i1 %2, label %then1, label %else2

else:                                             ; preds = %entry
  %3 = call i1 @"*String@Object#===<String, String>:Bool"(%String* bitcast ({ i32, i32, i32, [4 x i8] }* @str1 to %String*), %String* %method)
  br i1 %3, label %then3, label %else4

then1:                                            ; preds = %then
  br label %exit

else2:                                            ; preds = %then
  %4 = call i32 @"*Hash(Symbol, String)@Hash(K, V)#length<Hash(Symbol, String)>:Int32"(%"Hash(Symbol, String)"* %args)
  %5 = call %"Sendable::WrongNumberOfArguments"* @"*Sendable::WrongNumberOfArguments::new<String, Int32, Int32>:Sendable::WrongNumberOfArguments"(%String* bitcast ({ i32, i32, i32, [6 x i8] }* @str to %String*), i32 %4, i32 0)
  call void @"*raise<Sendable::WrongNumberOfArguments>:NoReturn"(%"Sendable::WrongNumberOfArguments"* %5)
  unreachable

exit:                                             ; preds = %then1
  call void @"*My#hello<My>:NoReturn"(%My* %self)
  unreachable

then3:                                            ; preds = %else
  %6 = call i32 @"*Hash(Symbol, String)@Hash(K, V)#length<Hash(Symbol, String)>:Int32"(%"Hash(Symbol, String)"* %args)
  %7 = icmp eq i32 %6, 0
  br i1 %7, label %then5, label %else6

else4:                                            ; preds = %else

then5:                                            ; preds = %then3
  br label %exit7

else6:                                            ; preds = %then3
  %8 = call i32 @"*Hash(Symbol, String)@Hash(K, V)#length<Hash(Symbol, String)>:Int32"(%"Hash(Symbol, String)"* %args)
  %9 = call %"Sendable::WrongNumberOfArguments"* @"*Sendable::WrongNumberOfArguments::new<String, Int32, Int32>:Sendable::WrongNumberOfArguments"(%String* bitcast ({ i32, i32, i32, [4 x i8] }* @str1 to %String*), i32 %8, i32 0)
  call void @"*raise<Sendable::WrongNumberOfArguments>:NoReturn"(%"Sendable::WrongNumberOfArguments"* %9)
  unreachable

exit7:                                            ; preds = %then5
}

declare i1 @"*String@Object#===<String, String>:Bool"(%String*, %String*)

declare i32 @"*Hash(Symbol, String)@Hash(K, V)#length<Hash(Symbol, String)>:Int32"(%"Hash(Symbol, String)"*)

declare %"Sendable::WrongNumberOfArguments"* @"*Sendable::WrongNumberOfArguments::new<String, Int32, Int32>:Sendable::WrongNumberOfArguments"(%String*, i32, i32)

declare void @"*raise<Sendable::WrongNumberOfArguments>:NoReturn"(%"Sendable::WrongNumberOfArguments"*)

; Function Attrs: noreturn
define void @"*My#hello<My>:NoReturn"(%My* %self) #1 {
entry:
  call void @"*My@Sendable#send<My, String>:NoReturn"(%My* %self, %String* bitcast ({ i32, i32, i32, [4 x i8] }* @str1 to %String*))
  unreachable
}

attributes #0 = { nounwind }
attributes #1 = { noreturn }
    case method



    when "hello"
      raise WrongNumberOfArguments.new("hello", args.length, 0) unless args.length == 0
      hello


    when "bye"
      raise WrongNumberOfArguments.new("bye", args.length, 0) unless args.length == 0
      bye

    else
      raise WrongInstanceMethod.new("My", "#{method}")
    end

Nil assertion failed
_init +171007 [0]
_init +173755 [0]
_init +3251488 [0]
_init +3247103 [0]
_init +3244025 [0]
_init +3282759 [0]
_init +3188090 [0]
_init +3188388 [0]
_init +3266960 [0]
_init +3193184 [0]
_init +3266960 [0]
_init +3193215 [0]
_init +3248139 [0]
_init +3244025 [0]
_init +3282759 [0]
_init +3188090 [0]
_init +3248139 [0]
_init +3244025 [0]
_init +3282759 [0]
_init +3188090 [0]
_init +3065700 [0]
_init +3052068 [0]
_init +2396865 [0]
_init +5900354 [0]
_init +5879350 [0]
__libc_start_main +247 [0]
_init +167975 [0]

Error: you've found a bug in the Crystal compiler. Please open an issue: https://github.com/manastech/crystal/issues
@Codcore
Copy link
Author

Codcore commented Jul 2, 2015

This happens when bye calls itself ( it's my typo, I mean p "bye" ):

def bye
    bye
  end

@asterite asterite added the kind:bug A bug in the code. Does not apply to documentation, specs, etc. label Jul 3, 2015
@asterite
Copy link
Member

The above is actually a stack overflow, so duplicate of #271

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind:bug A bug in the code. Does not apply to documentation, specs, etc. topic:compiler
Projects
None yet
Development

No branches or pull requests

2 participants