Skip to content

LLVM ERROR: Function addresses with offsets not supported #80318

@only-cliches

Description

@only-cliches

I've ran into an issue with one of my libraries that was preventing it from compiling with wasm-pack. It would otherwise compile just fine with rustc to other targets (no compiler errors) but when I would attempt to compile with wasm-pack I would get this cryptic error:

LLVM ERROR: Function addresses with offsets not supported
error: could not compile `hello-wasm`.

No line numbers, no error trace, just that.

After spending quite a while to find the offending block of code, I've discovered that the issue was caused by misusing the type system a bit.

Here's the offending code:

use wasm_bindgen::prelude::*;
use std::vec::Vec;

#[wasm_bindgen]
pub fn err() -> i32 {
    let vector: Vec<u8> = Vec::new();
    // In my library, I meant to use `core::u16::MAX` and did this instead
    let my_size = (u16::max as usize) - 1; // <- casting function as usize
    // `u16::max` is actually a function to compare two numbers and get the maximum between them
    if my_size > vector.len() {
        20
    } else {
        50
    }
}

I expected to see this happen: I think this is actually a type error. u16::max is a function and I'm casting it to a usize. I would hope the Rust compiler would yell at me for that or at least require me to write unsafe before I can cast a function to a usize.

Instead, this happened: The program compiles and runs just fine unless you attempt to compile it to wasm with wasm-pack build. If you run the function in a test, it spits out 20.

rustc --version --verbose:

rustc 1.47.0 (18bf6b4f0 2020-10-07)
binary: rustc
commit-hash: 18bf6b4f01a6feaf7259ba7cdae58031af1b7b39
commit-date: 2020-10-07
host: x86_64-apple-darwin
release: 1.47.0
LLVM version: 11.0

wasm-pack -V:

wasm-pack 0.9.1

Hoping to save someone else a few days of hair pulling!

Edit: A little bit more testing, it looks like the program compiles just fine if you change the line to this:

// let my_size = (u16::max as usize) - 1;
let my_size = (u16::max as usize)

So it seems like combining the cast with an operation causes the issue. Interestingly, not all operations cause the error.

// Doesn't compile with `wasm-pack`
let my_size = (u16::max as usize) + 1;
let my_size = (u16::max as usize) - 1;
let my_size = (u16::max as usize) + 2;
let my_size = (u16::max as usize) - 2;

// Compiles Fine with `wasm-pack`:
let my_size = (u16::max as usize) * 1;
let my_size = (u16::max as usize) / 1;
let my_size = (u16::max as usize) * 2;
let my_size = (u16::max as usize) / 2;

Activity

added
O-wasmTarget: WASM (WebAssembly), http://webassembly.org/
A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.
on Dec 23, 2020
camelid

camelid commented on Dec 23, 2020

@camelid
Member

I expected to see this happen: I think this is actually a type error. u16::max is a function and I'm casting it to a usize. I would hope the Rust compiler would yell at me for that or at least require me to write unsafe before I can cast a function to a usize.

I and other people would like to reduce the use of as (cc #79477 and RFC 2484), but that's a big undertaking and unlikely to happen soon. You should probably be using try_into().unwrap() instead of as so that your code panics if the value doesn't fit. In this case what you're doing is probably fine, but in general using as will cause the number to be truncated/wrapped if it doesn't fit in the type you're casting to.

Using try_into() will also give an error if you try to call it on a function.

By the way, why are you importing std::vec::Vec? It's in the prelude.

only-cliches

only-cliches commented on Dec 23, 2020

@only-cliches
Author

By the way, why are you importing std::vec::Vec? It's in the prelude.

I've been working in no_std so long it's become a habit!

Thanks for the reply, at the very least hopefully the next person to run into this has a head start on troubleshooting.

Mark-Simulacrum

Mark-Simulacrum commented on Dec 23, 2020

@Mark-Simulacrum
Member

This isn't a type error, I think, because u16::max is getting coerced into a function pointer which can then be cast into usize without any truncation. I'm a little surprised that the coercion occurred in that context but in any case that's not really the underlying cause of the bug here, I suspect.

only-cliches

only-cliches commented on Dec 23, 2020

@only-cliches
Author

Agreed, after further investigation It has something to do with casting a function into a usize, then adding or subtracting some value from that usize.

// Doesn't compile with `wasm-pack` (but otherwise compiles fine)
let my_size = (u16::max as usize) + 1;
let my_size = (u16::max as usize) - 1;
let my_size = (u16::max as usize) + 2;
let my_size = (u16::max as usize) - 2;

// Compiles Fine with `wasm-pack`:
let my_size = (u16::max as usize) * 1;
let my_size = (u16::max as usize) / 1;
let my_size = (u16::max as usize) * 2;
let my_size = (u16::max as usize) / 2;
added
T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
on Apr 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.C-bugCategory: This is a bug.O-wasmTarget: WASM (WebAssembly), http://webassembly.org/T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @Mark-Simulacrum@only-cliches@camelid@Noratrieb

        Issue actions

          LLVM ERROR: Function addresses with offsets not supported · Issue #80318 · rust-lang/rust