effekt-lang / effekt

A research language with effect handlers and lightweight effect polymorphism

Home Page:https://effekt-lang.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Wrong primitive names in LLVM I/O

jiribenes opened this issue · comments

Description

When I try to read from a file:

// repro.effekt

import io
import io/error
import io/files

def main() = eventloop(box {
  with on[IOError].panic;
  with filesystem;

  val contents = do readFile("repro.effekt")
  println(contents)
})

I get the following error:

bash-5.2$ effekt --backend=llvm repro.effekt
opt: ./out/repro.ll:1114:17: error: use of undefined value '@writeFile'
      call void @writeFile(i32 %fd_int, %Pos %buffer, i64 noundef %offset, ptr %onSuccess_ptr, ptr %onFailure_ptr) #0
                ^
Exception in thread "main" java.lang.RuntimeException: Nonzero exit value: 1
  [...]

Investigation 🔍

Upon taking a closer look at ./out/repro.ll, I can see that writeFile is truly neither defined nor declared there.
This happens even when I try to first build, then run.

If I had to guess, then the real name we're looking for is c_file_read in llvm/io.c

void c_file_read(int32_t fd, struct Pos buffer, int64_t offset, struct Neg* success, struct Neg* failure) {

which got renamed at the end of #469.
When investigating this, I also noticed that the LLVM definition corresponds to the C definition only with the ARM64 calling convention:
declare void @c_file_read([2 x i64], [2 x i64], i64, [2 x i64], [2 x i64])

I think it should be something like declare void @c_file_write(i32, %Pos, i64, %Neg*, %Neg*) instead? (or ptr, ptr for the last two, not sure)

I'm quite alarmed that the test in stdlib/io/files/async_file_io.effekt didn't catch this 🤔
https://github.com/effekt-lang/effekt/blob/cd741e8a4576c62ab318efd48fc0831958ba7e8d/examples/stdlib/io/files/async_file_io.effekt

EDIT: I tried running the LLVM stdlib tests and it appears that the test in question passes:

effekt.StdlibLLVMTests:
  + examples/stdlib/bytes/bytes.effekt (llvm) 2.928s
  + examples/stdlib/io/promise.effekt (llvm) 1.146s
  + examples/stdlib/io/files/async_file_io.effekt (llvm) 1.416s

The test works when ran directly:

$ effekt --backend=llvm examples/stdlib/io/files/async_file_io.effekt
Running program
Done
Some contents

{ msg: "Hello World!" }

done reading files.

but I don't understand why 😔
Well, the test only uses the readFile function and not the readFile operation which is then handled with filesystem. If I had to guess, the renaming is OK in one of them and not in the other...

It's writeFile, isn't it? Since we don't write files in the test, dead code elimination removes it before it causes problems