We designed LFortran to first "raise" the AST (Abstract Syntax Tree) to ASR (Abstract Semantic Representation). The ASR keeps all the semantics of the original code, but it is otherwise as abstract/simple as possible. Thus by definition it allows us to do any optimization possible, as ASR->ASR optimization pass. We do some already, we will do many more in the future. This optimizes all the things where you need to know the high level information about Fortran. Then once we can't do any more optimizations, we lower to LLVM. If in the future it turns out we need some representation between ASR and LLVM, such as MLIR, we can add it.
We also have a direct ASR->WASM and WASM->x64 machine code, and even direct ASR->machine code, but the ASR->LLVM backend is the most advanced, after that probably our ASR->C backend and after that our ASR->WASM backend.
Super cool stuff though
If LLVM has any downsides, it is that it is hard to run in the browser, so we don't use it for https://dev.lfortran.org/, and that it is slow to compile (both LLVM itself, as well as it makes LFortran slow to compile, compared to our direct WASM/x64 backends). But when it comes to runtime performance of the generated code, LLVM seems very good.
The further you stray from that, the worse is it.
I’ve actually never heard of an ASR before… sounds very interesting! Do you happen to have any resources I can read about this?
I'm not being argumentative, I'm actually really curious.
[0]: https://stackoverflow.com/questions/146159/is-fortran-easier...
subroutine foo(a, b, n)
integer n
real a(n), b(n)
do j = 1, n
a(j) = 2 * b(j)
end do
end
can be vectorized with no concern about what might happen if the `b` array shares any memory with the `a` array. The burden is on the programmer to not associate these dummy arguments on a call with data that violate this requirement.(This freedom from aliasing doesn't extend to Fortran's POINTER feature, nor does it apply to the ASSOCIATE construct, some compilers notwithstanding.)
What happens when the programmer pass aliasing a and b? Will it cause UB, like in C if you violate the restrict keyword?
This is just UB by another name
That's.. disappointing
The nice think about Fortran it that is does the sensible thing by default for the type of scientific computing codes that are inside it’s wheelhouse (the trivial example, it assumes arguments don’t alias by default).
C can beat anything, assuming unlimited effort. Fortran is nice for scientists who want to write pretty good code. Or grad students who are working on dissertations in something other than hand-tuning kernels.
For a long time Fortran was actually unbeatable and C did not suffice to specify all possible uses of assembly...
Of course, you can rewrite your C code by hand to generate the same LLVM code from Clang, as LFortran generates for the Fortran code. So in principle I think anything can be done in C, as anything can be done in assembly or machine code. But the advantage of Fortran is that it is higher level, and thus allows you to write code using arrays in a high level way and do not have to do many special things as a programmer, and the compiler can then highly optimize your code. While in C very often you might need to do some of these optimizations by hand as a user.
In C this is pretty much impossible.
To be fair, there are C like languages (ispc, glsl) which makes this work with heroic compiler efforts.
That used to be true a long time ago but since the restrict keyword was introduced in C99 it's not really true any more.