certik / minpack

Library for solving nonlinear equations and nonlinear least squares problems
http://www.netlib.org/minpack/
Other
32 stars 10 forks source link

ASR verify pass error: example_primes #13

Open Pranavchiku opened 1 year ago

Pranavchiku commented 1 year ago
ASR verify pass error: ASR verify: Function find_fit depends on expr but isn't found in its dependency list.
  --> /home/pranavchiku/minpack/examples/example_primes.f90:23:1 - 63:1
   |
23 |    subroutine find_fit(data_x, data_y, expr, pars)
   |    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
...
   |
63 |    
   | ...^ failed here

I am trying to have a minimal reproducible error, so that it can be easy to debug.

Pranavchiku commented 1 year ago
subroutine find_fit(x, expr)
    real :: x
    interface
        function expr(x) result(y)
            real, intent(in) :: x
            real :: y
        end function
    end interface
end subroutine

Should ASR node of find_fit subroutine have expr as dependency? if yes, it is not having the provision for same which we need to implement to get minpack/examples/example_primes working.

certik commented 1 year ago

I think expr shouldn't be in dependencies list, since it is not an external function, but rather a call back, or "function type". See https://github.com/lfortran/lfortran/issues/1162 for more details on this.

Pranavchiku commented 1 year ago
subroutine find_fit(x, expr)
    real :: x
    interface
        function expr(x) result(y)
            real, intent(in) :: x
            real :: y
        end function
    end interface
end subroutine

program main
    real :: x
    call find_fit(x, f)
    contains
    function f(x) result(y)
        real, intent(in) :: x
        real :: y
    end function
end program
certik commented 1 year ago

With the latest idea in https://github.com/lfortran/lfortran/issues/1162#issuecomment-1372487399, the expr above becomes a Variable called expr of type FunctionType (no name).

And f becomes a Var that points to a Function f.

certik commented 1 year ago

Regarding:

subroutine find_fit(x, expr_arg)
    real :: x
    interface
        function expr(x) result(y)
            real, intent(in) :: x
            real :: y
        end function
    end interface
    procedure(expr) :: expr_arg
end subroutine

Here expr_arg is a Variable of type FunctionType (no name). And expr is a NamedFunctionType symbol. Both expr_arg and expr point to the same FunctionType. But otherwise there is no link between them, which might not be ideal, but it should work.

certik commented 1 year ago

All this refactor can be done later.

For now, we already have the callbacks working in some way, see integration_tests/callback_*.f90. Let's create a minimal reproducible example of a bug that you are hitting, and then let's see if there is a way to fix it within the current design, which would unblock us. And we can do the full redesign later.

Pranavchiku commented 1 year ago
module find_fit_module
   implicit none
   public

contains

   subroutine find_fit(expr)
      interface
         function expr(x) result(y)
            implicit none
            real, intent(in) :: x(:)
            real :: y(size(x))
         end function
      end interface

   end subroutine

end module

program main
   use find_fit_module, only: find_fit
   implicit none
   call find_fit(expression)
contains

   function expression(x) result(y)
      real, intent(in) :: x(:)
      real :: y(size(x))
      y = x
   end function

end program

Throws

$ lfortran a.f90
ASR verify pass error: ASR verify: Var::m_v `x` cannot point outside of its symbol table
Internal Compiler Error: Unhandled exception
Traceback (most recent call last):
  Binary file "/home/pranavchiku/lfortran/src/bin/lfortran", in _start()
  File "./csu/../csu/libc-start.c", line 392, in __libc_start_main_impl()
  File "./csu/../sysdeps/nptl/libc_start_call_main.h", line 58, in __libc_start_call_main()
  File "/home/pranavchiku/lfortran/src/bin/lfortran.cpp", line 1938, in ??
    err = compile_to_object_file(arg_file, tmp_o, false,
  File "/home/pranavchiku/lfortran/src/bin/lfortran.cpp", line 865, in ??
    res = fe.get_llvm3(*asr, lpm, diagnostics, infile);
  File "/home/pranavchiku/lfortran/src/lfortran/fortran_evaluator.cpp", line 342, in LCompilers::FortranEvaluator::get_llvm3(LCompilers::ASR::TranslationUnit_t&, LCompilers::PassManager&, LCompilers::diag::Diagnostics&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
    compiler_options, run_fn, infile);
  File "/home/pranavchiku/lfortran/src/libasr/codegen/asr_to_llvm.cpp", line 6794, in LCompilers::asr_to_llvm(LCompilers::ASR::TranslationUnit_t&, LCompilers::diag::Diagnostics&, llvm::LLVMContext&, Allocator&, LCompilers::PassManager&, LCompilers::CompilerOptions&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
    pass_manager.apply_passes(al, &asr, pass_options, diagnostics);
  File "/home/pranavchiku/lfortran/src/libasr/pass/pass_manager.h", line 209, in LCompilers::PassManager::apply_passes(Allocator&, LCompilers::ASR::TranslationUnit_t*, LCompilers::PassOptions&, LCompilers::diag::Diagnostics&)
    _apply_passes(al, asr, _passes, pass_options, diagnostics);
LCompilersException: Verify failed
HarshitaKalani commented 1 year ago

With the latest main, this is the error:

(lf) harshita@harshita-linux:~/Desktop/lfortran$ lfortran a.f90
; ModuleID = 'LFortran'
source_filename = "LFortran"

%array = type { float*, i32, %dimension_descriptor*, i1, i32 }
%dimension_descriptor = type { i32, i32, i32 }

define void @__module_find_fit_module_find_fit(void (%array*, float*)* %expr) {
.entry:
  br label %return

return:                                           ; preds = %.entry
  ret void
}

declare void @expr(%array*, float*)

define void @expression_x(float* %x, i32* %__1x, i32* %__2x, float* %y) {
.entry:
  %__1_t = alloca i32, align 4
  %__1_v = alloca i32, align 4
  %0 = load i32, i32* %__1x, align 4
  store i32 %0, i32* %__1_v, align 4
  store i32 0, i32* %__1_t, align 4
  br label %loop.head

loop.head:                                        ; preds = %loop.body, %.entry
  %1 = load i32, i32* %__1_t, align 4
  %2 = add i32 %1, 1
  %3 = load i32, i32* %__2x, align 4
  %4 = mul i32 1, %3
  %5 = add i32 %4, 1
  %6 = sub i32 %5, 1
  %7 = icmp sle i32 %2, %6
  br i1 %7, label %loop.body, label %loop.end

loop.body:                                        ; preds = %loop.head
  %8 = load i32, i32* %__1_t, align 4
  %9 = add i32 %8, 1
  store i32 %9, i32* %__1_t, align 4
  %10 = load i32, i32* %__1_t, align 4
  %11 = load i32, i32* %__2x, align 4
  %12 = mul i32 1, %11
  %13 = sub i32 %10, 1
  %14 = mul i32 1, %13
  %15 = add i32 0, %14
  %16 = mul i32 1, %12
  %17 = getelementptr inbounds float, float* %y, i32 %15
  %18 = load i32, i32* %__1_v, align 4
  %19 = load i32, i32* %__1x, align 4
  %20 = load i32, i32* %__2x, align 4
  %21 = sub i32 %18, %19
  %22 = mul i32 1, %21
  %23 = add i32 0, %22
  %24 = mul i32 1, %20
  %25 = getelementptr inbounds float, float* %x, i32 %23
  %26 = load float, float* %25, align 4
  store float %26, float* %17, align 4
  %27 = load i32, i32* %__1_v, align 4
  %28 = add i32 %27, 1
  store i32 %28, i32* %__1_v, align 4
  br label %loop.head

loop.end:                                         ; preds = %loop.head
  br label %return

return:                                           ; preds = %loop.end
  ret void
}

define i32 @main(i32 %0, i8** %1) {
.entry:
  call void @_lpython_set_argv(i32 %0, i8** %1)
  call void @__module_find_fit_module_find_fit(void (float*, i32*, i32*, float*)* @expression_x)
  ret i32 0
}

declare void @_lpython_set_argv(i32, i8**)
code generation error: asr_to_llvm: module failed verification. Error:
Call parameter type does not match function signature!
void (float*, i32*, i32*, float*)* @expression_x
 void (%array*, float*)*  call void @__module_find_fit_module_find_fit(void (float*, i32*, i32*, float*)* @expression_x)