Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LLVM ERROR: Function addresses with offsets not supported #80318

Open
only-cliches opened this issue Dec 23, 2020 · 4 comments
Open

LLVM ERROR: Function addresses with offsets not supported #80318

only-cliches opened this issue Dec 23, 2020 · 4 comments
Labels
A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. C-bug Category: This is a bug. O-wasm Target: WASM (WebAssembly), http://webassembly.org/ T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@only-cliches
Copy link

only-cliches commented Dec 23, 2020

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;
@only-cliches only-cliches added the C-bug Category: This is a bug. label Dec 23, 2020
@camelid camelid added O-wasm Target: WASM (WebAssembly), http://webassembly.org/ A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. labels Dec 23, 2020
@camelid
Copy link
Member

camelid commented Dec 23, 2020

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
Copy link
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
Copy link
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
Copy link
Author

only-cliches commented Dec 23, 2020

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;

@Nilstrieb Nilstrieb added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Apr 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. C-bug Category: This is a bug. O-wasm Target: WASM (WebAssembly), http://webassembly.org/ T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants