Stream: compiler development

Topic: Windows roc_mmap issue


view this post on Zulip Luke Boswell (Jul 24 2023 at 08:21):

Almost all the test failures on Windows I am experiencing look to be the same issue. Something like the following.

thread 'main' panicked at 'extern function roc_mmap is not defined by the builtins', crates\compiler\gen_llvm\src\llvm\externs.rs:176:17

So, I thought I might try and investigate further. It looks liks roc_mmap is provided in the bitcode. When I run the tests for zig builtins in crates\compiler\builtins\bitcode I get the following lld-link errors.

PS C:\Users\bosyl\Documents\GitHub\roc\crates\compiler\builtins\bitcode> zig build test
lld-link: error: undefined symbol: getppid
>>> referenced by C:\Users\bosyl\Documents\GitHub\roc\crates\compiler\builtins\bitcode\src\utils.zig:28
>>>               C:\Users\bosyl\Documents\GitHub\roc\crates\compiler\builtins\bitcode\zig-cache\o\956e3fa7e43377a9e7882b44adf58cc5\test.obj:(roc_getppid)

lld-link: error: undefined symbol: mmap
>>> referenced by C:\Users\bosyl\Documents\GitHub\roc\crates\compiler\builtins\bitcode\src\utils.zig:39
>>>               C:\Users\bosyl\Documents\GitHub\roc\crates\compiler\builtins\bitcode\zig-cache\o\956e3fa7e43377a9e7882b44adf58cc5\test.obj:(roc_mmap)

lld-link: error: undefined symbol: shm_open
>>> referenced by C:\Users\bosyl\Documents\GitHub\roc\crates\compiler\builtins\bitcode\src\utils.zig:36
>>>               C:\Users\bosyl\Documents\GitHub\roc\crates\compiler\builtins\bitcode\zig-cache\o\956e3fa7e43377a9e7882b44adf58cc5\test.obj:(roc_shm_open)
error: LLDReportedFailure
The following command exited with error code 1:
C:\ProgramData\chocolatey\lib\zig\tools\zig-windows-x86_64-0.9.1\zig.exe test C:\Users\bosyl\Documents\GitHub\roc\crates\compiler\builtins\bitcode\src\main.zig -lc --cache-dir C:\Users\bosyl\Documents\GitHub\roc\crates\compiler\builtins\bitcode\zig-cache --global-cache-dir C:\Users\bosyl\AppData\Local\zig --name test
error: the following build command failed with exit code 1:
C:\Users\bosyl\Documents\GitHub\roc\crates\compiler\builtins\bitcode\zig-cache\o\52b924dff34895983671b1f52442ea3d\build.exe C:\ProgramData\chocolatey\lib\zig\tools\zig-windows-x86_64-0.9.1\zig.exe C:\Users\bosyl\Documents\GitHub\roc\crates\compiler\builtins\bitcode C:\Users\bosyl\Documents\GitHub\roc\crates\compiler\builtins\bitcode\zig-cache C:\Users\bosyl\AppData\Local\zig test

ChatGPT tells me the following

It looks like you're getting linker errors when trying to compile your Zig program, which is probably because the functions getppid, mmap, and shm_open are not found.
The reason you're encountering this issue is likely because these functions are not available on Windows. These are POSIX (Portable Operating System Interface) system calls:
getppid: This function returns the parent process id. On Windows, you can use GetCurrentProcessId and GetParentProcessId instead.
mmap: This function is used to map a file or other object into memory. On Windows, you can use CreateFileMapping and MapViewOfFile.
shm_open: This function creates or opens a named shared memory object. On Windows, you can use CreateFileMapping with a unique name to achieve similar functionality.

view this post on Zulip Anton (Jul 24 2023 at 09:16):

In c hosts we do:

void* roc_mmap(void* addr, int length, int prot, int flags, int fd, int offset) {
#ifdef _WIN32
    return addr;
#else
    return mmap(addr, length, prot, flags, fd, offset);
#endif

I don't really know zig, but in compiler/builtins/bitcode/src/utils.zig we don't have an if:

extern fn mmap(addr: ?*anyopaque, length: c_uint, prot: c_int, flags: c_int, fd: c_int, offset: c_uint) *anyopaque;

So that may be a problem.

I don't think I've seen extern function roc_mmap is not defined by the builtins when fixing windows issues a couple of months ago, so that may also be a recently introduced issue.

view this post on Zulip Folkert de Vries (Jul 24 2023 at 09:47):

I think it's specific to some platforms. In any case, we should not be using mmap on windows, so providing a dummy implementation is fine

view this post on Zulip Luke Boswell (Jul 24 2023 at 10:14):

Sounds good. Do you have any pointers where the dummy implementation should go? Also, should zig tests run on windows?

view this post on Zulip Folkert de Vries (Jul 24 2023 at 10:23):

they kind of should

view this post on Zulip Folkert de Vries (Jul 24 2023 at 10:25):

re the error, I think here

        unreachable_function(env, "roc_getppid");
        unreachable_function(env, "roc_mmap");
        unreachable_function(env, "roc_shm_open");

        add_sjlj_roc_panic(env)
    }
}

fn unreachable_function(env: &Env, name: &str) {
    // The type of this function (but not the implementation) should have
    // already been defined by the builtins, which rely on it.
    let fn_val = match env.module.get_function(name) {
        Some(f) => f,
        None => panic!("extern function {name} is not defined by the builtins"),
    };

(you'll find this by searching for string in the panic here)

view this post on Zulip Folkert de Vries (Jul 24 2023 at 10:26):

we should just not call unreachable_function(env, ... on windows for roc_mmap, ppid, and shm_open I think

view this post on Zulip Folkert de Vries (Jul 24 2023 at 10:26):

so just add some #[cfg(not(windows))] would be my guess

view this post on Zulip Luke Boswell (Jul 24 2023 at 10:41):

        #[cfg(not(windows))]
        {
            unreachable_function(env, "roc_getppid");
            unreachable_function(env, "roc_mmap");
            unreachable_function(env, "roc_shm_open");
        }
 ```

Seems to have done it. Ran one test and it passed. I'll try running all of test_gen next

view this post on Zulip Luke Boswell (Jul 24 2023 at 11:10):

Ok so running cargo test --release --locked --package test_gen --test test_gen gave me this.

Screenshot-2023-07-24-210147.png

I'm not sure why that crashes the test runner. If I disable the decode_derive_decoder_for_opaquewhich overflowed its stack I get the same issue where something is causing exit code: 0xc0000005, STATUS_ACCESS_VIOLATION). I've also tried running in debug mode and get the same issue.

view this post on Zulip Folkert de Vries (Jul 24 2023 at 11:21):

what might be helpful here is cargo nextest-gen-llvm --no-fail-fast (may need cargo install nextest or similar)

view this post on Zulip Folkert de Vries (Jul 24 2023 at 11:21):

that should run all the tests and not stop when one of them crashes

view this post on Zulip Folkert de Vries (Jul 24 2023 at 11:21):

so we can get an overview of what fails, maybe there are patterns

view this post on Zulip Luke Boswell (Jul 24 2023 at 11:22):

I'll give that a go.

Just ran mono tests also

failures:

---- branch_store_variable stdout ----
`git diff "generated/branch_store_variable.txt"` failed
thread 'branch_store_variable' panicked at 'internal error: entered unreachable code', crates\compiler\test_mono\src/tests.rs:232:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace


failures:
    branch_store_variable

test result: FAILED. 156 passed; 1 failed; 7 ignored; 0 measured; 0 filtered out; finished in 9.80s

view this post on Zulip Folkert de Vries (Jul 24 2023 at 11:23):

that error means that git diff failed?!

view this post on Zulip Folkert de Vries (Jul 24 2023 at 11:24):

maybe the file doesn't exist?

view this post on Zulip Luke Boswell (Jul 25 2023 at 07:53):

Here are the results for test-gen in case this helps.

view this post on Zulip Folkert de Vries (Jul 25 2023 at 07:59):

hmm, there is this chunk

   FAIL [   3.124s] test_gen::test_gen gen_num::to_i64_checked_larger_width_signed_fits_neg
        FAIL [   3.978s] test_gen::test_gen gen_num::to_i64_checked_larger_width_signed_fits_pos
        FAIL [   2.370s] test_gen::test_gen gen_num::to_i64_checked_larger_width_signed_oob_neg
        FAIL [   2.326s] test_gen::test_gen gen_num::to_i64_checked_larger_width_signed_oob_pos
        FAIL [   2.134s] test_gen::test_gen gen_num::to_i64_checked_larger_width_unsigned_fits_pos
        FAIL [   2.151s] test_gen::test_gen gen_num::to_i64_checked_larger_width_unsigned_oob_pos

view this post on Zulip Folkert de Vries (Jul 25 2023 at 07:59):

they fail "normally". can you find an error message for them?

view this post on Zulip Folkert de Vries (Jul 25 2023 at 07:59):

(others abort because they do the equivalent of a segfault)

view this post on Zulip Luke Boswell (Jul 25 2023 at 08:04):

Something like thread 'gen_num::to_i64_checked_larger_width_signed_fits_neg' panicked at 'LLVM error: Did not get return value from bitcode function "roc_builtins.num.int_to_i64_checking_max_and_min.i128"'

view this post on Zulip Folkert de Vries (Jul 25 2023 at 08:05):

and then for the other issues, I suspect return_tuple_3 is the easiest to debug. that'll be an adventure in assembly though

view this post on Zulip Folkert de Vries (Jul 25 2023 at 08:06):

hmm, ok, strange. I think it would help to see the LLVM IR for that failing i128 test. I think when a test fails we try to save that IR

view this post on Zulip Folkert de Vries (Jul 25 2023 at 08:06):

but maybe that is skipped on windows

view this post on Zulip Luke Boswell (Jul 25 2023 at 08:07):

view this post on Zulip Folkert de Vries (Jul 25 2023 at 08:09):

right, so on windows this function does not return, apparently

view this post on Zulip Folkert de Vries (Jul 25 2023 at 08:09):

and you pass in effectively a &mut result for it to write the value into

view this post on Zulip Folkert de Vries (Jul 25 2023 at 08:10):

so that will have to be special-cased

view this post on Zulip Folkert de Vries (Jul 25 2023 at 08:13):

in particular, I suspect that this logic is not entirely correct

                        if target_int_width.stack_size() as usize > env.target_info.ptr_size() {
                            let bitcode_return_type =
                                zig_to_int_checked_result_type(env, target_int_width.type_name());

                            call_bitcode_fn_fixing_for_convention(
                                env,
                                layout_interner,
                                bitcode_return_type,
                                &[arg.into()],
                                return_layout,
                                intrinsic,
                            )
                        } else {
                            call_bitcode_fn(env, &[arg.into()], intrinsic)
                        }

view this post on Zulip Luke Boswell (Jul 25 2023 at 08:17):

They run through the else branch when I add dbg's

view this post on Zulip Folkert de Vries (Jul 25 2023 at 08:18):

yeah, I think that is incorrect

view this post on Zulip Luke Boswell (Jul 25 2023 at 08:43):

So does this mean the builtin function when it is called by env.builder.build_call() isn't returning a BasicValueEnum type?

view this post on Zulip Folkert de Vries (Jul 25 2023 at 08:44):

yes

view this post on Zulip Folkert de Vries (Jul 25 2023 at 08:45):

it's a void function

view this post on Zulip Luke Boswell (Jul 25 2023 at 08:46):

pub fn exportToIntCheckingMaxAndMin(comptime From: type, comptime To: type, comptime name: []const u8) void

view this post on Zulip Folkert de Vries (Jul 25 2023 at 08:56):

eh yes but that function is the generator

view this post on Zulip Folkert de Vries (Jul 25 2023 at 08:56):

it makes available a function with some different type

view this post on Zulip Folkert de Vries (Jul 25 2023 at 08:56):

it's like a macro

view this post on Zulip Luke Boswell (Jul 25 2023 at 08:59):

let xxx = call_bitcode_fn_help(env, args, fn_name);

    dbg!(&xxx);

    xxx.try_as_basic_value()
        .left()
        .unwrap_or_else(|| {
            panic!("LLVM error: Did not get return value from bitcode function {fn_name:?}")
        })

Gives

[crates\compiler\gen_llvm\src\llvm\bitcode.rs:35] &xxx = CallSiteValue(
    Value {
        name: "",
        address: 0x000001b9326ddd10,
        is_const: false,
        is_null: false,
        is_undef: false,
        llvm_value: "  call void @roc_builtins.num.int_to_i64_checking_max_and_min.i128(i128 noalias nocapture nonnull sret(%\"num.ToIntCheckedResult(i64)\") %\"#arg1\"), !dbg !9",
        llvm_type: "void",
    },
)

view this post on Zulip Folkert de Vries (Jul 25 2023 at 09:22):

yes, exactly

view this post on Zulip Folkert de Vries (Jul 25 2023 at 09:23):

it returns void, and the first argument is a pointer to write the result into


Last updated: Jul 06 2025 at 12:14 UTC