LFortran Minimum Viable Product (MVP)

Good point. I think you can define a module. But you have to currently create the new line by hand (see the help message). We need to improve our new line logic to create a new line when you start a module.

Took two days, but now all my systems run FreeBSD 13. LFortran 0.14 compiles with installed LLVM sources, and all tests are passed (ctest).

But trying to compile outputs:

$ lfortran -o test test.f              
/usr/local/bin/ld: /tmp//ccWcqm2Q.o: in function `MAIN__':
test.f:(.text+0x3f): undefined reference to `_gfortran_st_write'
/usr/local/bin/ld: test.f:(.text+0x58): undefined reference to `_gfortran_transfer_character_write'
/usr/local/bin/ld: test.f:(.text+0x67): undefined reference to `_gfortran_st_write_done'
/usr/local/bin/ld: /tmp//ccWcqm2Q.o: in function `main':
test.f:(.text+0x8a): undefined reference to `_gfortran_set_args'
/usr/local/bin/ld: test.f:(.text+0x99): undefined reference to `_gfortran_set_options'
collect2: error: ld returned 1 exit status
The command 'gcc -o test test.f  -L"/usr/home/user/.local/bin/../share/lfortran/lib" -Wl,-rpath,"/usr/home/user/.local/bin/../share/lfortran/lib" -llfortran_runtime -lm' failed
1 Like

@interkosmos awesome!

It’s weird that it would try to link some gfortran’s symbols.

Ah I see — it seems to be calling gcc on the .f files which in turn calls GFortran (that might be a bug in LFortran). For fixed-form, use lfortran --fixed-form -o test test.f I think that should work. The fixed-form parser is still experimental.

Fixed form doesn’t seem to work even with --fixed-form (same error). Trying to compile a free form source file:

$ lfortran -o test test.f90
Compiling Fortran files to object files requires the LLVM backend to be enabled. Recompile with `WITH_LLVM=yes`.

But LFortran has been compiled with WITH_LLVM=yes. Nevermind, flag was not set, build fails:

$ make -j4
[ 54%] Building CXX object src/lfortran/CMakeFiles/lfortran_lib.dir/codegen/llvm_utils.cpp.o
In file included from /tmp/lfortran-0.14.0/src/lfortran/codegen/evaluator.cpp:53:
/tmp/lfortran-0.14.0/src/lfortran/codegen/KaleidoscopeJIT.h:22:10: fatal error: 'llvm/ExecutionEngine/Orc/LambdaResolver.h' file not found
#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
[…]

Had to add the include search path manually:

# cmake -DWITH_LLVM=YES -DCMAKE_CXX_FLAGS=-I/usr/src/contrib/llvm-project/llvm/include .

Next error:

# make -j4
[ 74%] Built target x                                                      
[ 75%] Building CXX object src/lfortran/tests/CMakeFiles/test_parse.dir/test_parse.cpp.o
[ 76%] Linking CXX executable test_llvm                                                                                                                
[ 77%] Linking CXX executable test_ast
[ 77%] Built target test_ast                                               
ld: error: undefined symbol: llvm::object::ObjectFile::createObjectFile(llvm::MemoryBufferRef, llvm::file_magic)
>>> referenced by evaluator.cpp                                            
>>>               evaluator.cpp.o:(llvm::orc::LegacyRTDyldObjectLinkingLayer::addObject(unsigned long, std::__1::unique_ptr<llvm::MemoryBuffer, std::__
1::default_delete<llvm::MemoryBuffer> >)) in archive ../liblfortran_lib.a
>>> did you mean: llvm::object::ObjectFile::createObjectFile(llvm::MemoryBufferRef, llvm::file_magic, bool)
>>> defined in: /usr/local/llvm12/lib/libLLVMObject.a(ObjectFile.cpp.o)
ld: error: undefined symbol: llvm::orc::JITSymbolResolverAdapter::JITSymbolResolverAdapter(llvm::orc::ExecutionSession&, llvm::orc::SymbolResolver&, ll
vm::orc::MaterializationResponsibility*)
[…]
[ 78%] Building CXX object src/bin/CMakeFiles/cpptranslate.dir/cpptranslate.cpp.o                                                                      
c++: error: linker command failed with exit code 1 (use -v to see invocation)
--- src/lfortran/tests/test_llvm ---                                       
*** [src/lfortran/tests/test_llvm] Error code 1

Yeah, typical issues with depending on a big 3rd party library. Did you say this is LLVM 11?

Well, I’ve LLVM 11 (base), as well as 12 and 14 (ports) installed. CMake is using the wrong version:

-- Found LLVM 12.0.1                                                                                                                                   
-- Using LLVMConfig.cmake in: /usr/local/llvm12/lib/cmake/llvm                                                                                         
                                                                                                                                                       
                                                                                                                                                       
Configuration results                                                                                                                                  
---------------------                                                                                                                                  
LFORTRAN_VERSION: 0.14.0                                                                                                                               
CPACK_PACKAGE_FILE_NAME: lfortran-0.14.0-FreeBSD                                                                                                       
C compiler      : /usr/bin/cc                                                                                                                          
C++ compiler    : /usr/bin/c++
[…]

And then chooses cc and c++ from base.

Yes, I haven’t updated things to compile with LLVM 12 yet. Here is the part that finds LLVM in CMake:

If you know how to fix it let me know. Usually something like this should work:

CMAKE_PREFIX_PATH=/usr/local/llvm11/ cmake -DWITH_LLVM=yes .

That should force cmake to find the LLVM 11 first.

Taking the CMakeLists.txt you’ve linked and forcing LLVM 12 still leads to:

[ 75%] Building CXX object src/lfortran/tests/CMakeFiles/test_parse.dir/test_parse.cpp.o
[ 76%] Linking CXX executable test_llvm
ld: error: undefined symbol: llvm::object::ObjectFile::createObjectFile(llvm::MemoryBufferRef, llvm::file_magic)
>>> referenced by evaluator.cpp
>>>               evaluator.cpp.o:(llvm::orc::LegacyRTDyldObjectLinkingLayer::addObject(unsigned long, std::__1::unique_ptr<llvm::MemoryBuffer, std::__
1::default_delete<llvm::MemoryBuffer> >)) in archive ../liblfortran_lib.a
>>> did you mean: llvm::object::ObjectFile::createObjectFile(llvm::MemoryBufferRef, llvm::file_magic, bool)
>>> defined in: /usr/local/llvm12/lib/libLLVMObject.a(ObjectFile.cpp.o)
ld: error: undefined symbol: llvm::orc::JITSymbolResolverAdapter::JITSymbolResolverAdapter(llvm::orc::ExecutionSession&, llvm::orc::SymbolResolver&, ll
vm::orc::MaterializationResponsibility*)

I also had to use some include files from LLVM 11, as they were not shipped with 12, like llvm/ExecutionEngine/Orc/LambdaResolver.h.

You have to force LLVM 11, not 12. LLVM 12 does not work with LFortran yet.

Forcing 11 shows the same error as posted above:

$ cmake -DWITH_LLVM=YES -DCMAKE_CXX_FLAGS=-I/usr/src/contrib/llvm-project/llvm/include -DCMAKE_C_FLAGS=-I/usr/src/contrib/llvm-project/llvm/include -DCMAKE_CXX_COMPILER=c++ -DCMAKE_C_COMPILER=cc -DCMAKE_PREFIX_PATH=/usr .

But there is only one CMake configuration for LLVM available, and it’s for 12. So, still a version mismatch? For instance, adding find_package(LLVM 11 REQUIRED) to CMakeLists.txt:

CMake Error at CMakeLists.txt:93 (find_package):
  Could not find a configuration file for package "LLVM" that is compatible
  with requested version "11".

  The following configuration files were considered but not accepted:

    /usr/local/llvm12/lib/cmake/llvm/LLVMConfig.cmake, version: 12.0.1

Well, have to try another Jail then, as the installed PostgreSQL 12 depends on LLVM 12, so I can’t simply remove the package.

That’s done here: src/lfortran/utils.cpp Ā· d9c16911407273434a81ae12ca15655e0f44d082 Ā· lfortran / lfortran Ā· GitLab, as you can see it’s a bit primitive for now and not sufficient — for example the platform macOS is not enough to determine the correct ABI (Intel vs ARM), neither with Windows, which can be either MSVC or GCC, and they differ in ABI. We have also implemented LLVM’s target triple (such as x86_64-w64-windows-gnu, x86_64-pc-windows-msvc). I wonder if we should just use that.