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

logos-codegen test failure in s390x #427

Closed
LecrisUT opened this issue Oct 8, 2024 · 13 comments · Fixed by #431
Closed

logos-codegen test failure in s390x #427

LecrisUT opened this issue Oct 8, 2024 · 13 comments · Fixed by #431
Labels
bug Something isn't working

Comments

@LecrisUT
Copy link
Contributor

LecrisUT commented Oct 8, 2024

Hi, I am updating logos to 0.14.2 on Fedora, when I've encountered the following issue when building for s390x:

running 2 tests
test test_codegen::case_1 ... ok
test test_codegen::case_2 ... FAILED

I have diffed the results of each one, and they look drastically different:

left
impl<'s> ::logos::Logos<'s> for Token {
    type Error = ();
    type Extras = ();
    type Source = [u8];
    fn lex(lex: &mut ::logos::Lexer<'s, Self>) {
        use ::logos::internal::{LexerInternal, CallbackResult};
        type Lexer<'s> = ::logos::Lexer<'s, Token>;
        fn _end<'s>(lex: &mut Lexer<'s>) { lex.end() }
        fn _error<'s>(lex: &mut Lexer<'s>) {
            lex.bump_unchecked(1);
            lex.error();
        } macro_rules! _fast_loop { ($ lex : ident , $ test : ident , $ miss : expr) => { while let Some (arr) = $ lex . read :: < & [u8 ; 16] > () { if $ test (arr [0]) { if $ test (arr [1]) { if $ test (arr [2]) { if $ test (arr [3]) { if $ test (arr [4]) { if $ test (arr [5]) { if $ test (arr [6]) { if $ test (arr [7]) { if $ test (arr [8]) { if $ test (arr [9]) { if $ test (arr [10]) { if $ test (arr [11]) { if $ test (arr [12]) { if $ test (arr [13]) { if $ test (arr [14]) { if $ test (arr [15]) { $ lex . bump_unchecked (16) ; continue ; } $ lex . bump_unchecked (15) ; return $ miss ; } $ lex . bump_unchecked (14) ; return $ miss ; } $ lex . bump_unchecked (13) ; return $ miss ; } $ lex . bump_unchecked (12) ; return $ miss ; } $ lex . bump_unchecked (11) ; return $ miss ; } $ lex . bump_unchecked (10) ; return $ miss ; } $ lex . bump_unchecked (9) ; return $ miss ; } $ lex . bump_unchecked (8) ; return $ miss ; } $ lex . bump_unchecked (7) ; return $ miss ; } $ lex . bump_unchecked (6) ; return $ miss ; } $ lex . bump_unchecked (5) ; return $ miss ; } $ lex . bump_unchecked (4) ; return $ miss ; } $ lex . bump_unchecked (3) ; return $ miss ; } $ lex . bump_unchecked (2) ; return $ miss ; } $ lex . bump_unchecked (1) ; return $ miss ; } return $ miss ; } while $ lex . test ($ test) { $ lex . bump_unchecked (1) ; } $ miss } ; } #[inline]
        fn goto11_ctx11_x<'s>(lex: &mut Lexer<'s>) { lex.set(Ok(Token::Any)); }
        #[inline]
        fn goto2_ctx11_x<'s>(lex: &mut Lexer<'s>) { lex.set(Ok(Token::AnyUnicode)); }
        #[inline]
        fn goto18_ctx11_x<'s>(lex: &mut Lexer<'s>) {
            match lex.read::<&[u8; 3usize]>() {
                Some([128u8..=191u8, 128u8..=191u8, 128u8..=191u8]) => {
                    lex.bump_unchecked(3usize);
                    goto2_ctx11_x(lex)
                }
                _ => goto11_ctx11_x(lex),
            }
        }
        #[inline]
        fn goto1_x<'s>(lex: &mut Lexer<'s>) { lex.set(Ok(Token::Newline)); }
        #[inline]
        fn goto17_ctx11_x<'s>(lex: &mut Lexer<'s>) {
            match lex.read::<&[u8; 3usize]>() {
                Some([144u8..=191u8, 128u8..=191u8, 128u8..=191u8]) => {
                    lex.bump_unchecked(3usize);
                    goto2_ctx11_x(lex)
                }
                _ => goto11_ctx11_x(lex),
            }
        }
        #[inline]
        fn goto11_x<'s>(lex: &mut Lexer<'s>) { lex.set(Ok(Token::Any)); }
        #[inline]
        fn goto16_ctx11_x<'s>(lex: &mut Lexer<'s>) {
            match lex.read::<&[u8; 2usize]>() {
                Some([128u8..=159u8, 128u8..=191u8]) => {
                    lex.bump_unchecked(2usize);
                    goto2_ctx11_x(lex)
                }
                _ => goto11_ctx11_x(lex),
            }
        }
        #[inline]
        fn goto15_ctx11_x<'s>(lex: &mut Lexer<'s>) {
            match lex.read::<&[u8; 2usize]>() {
                Some([128u8..=191u8, 128u8..=191u8]) => {
                    lex.bump_unchecked(2usize);
                    goto2_ctx11_x(lex)
                }
                _ => goto11_ctx11_x(lex),
            }
        }
        #[inline]
        fn goto14_ctx11_x<'s>(lex: &mut Lexer<'s>) {
            match lex.read::<&[u8; 2usize]>() {
                Some([160u8..=191u8, 128u8..=191u8]) => {
                    lex.bump_unchecked(2usize);
                    goto2_ctx11_x(lex)
                }
                _ => goto11_ctx11_x(lex),
            }
        }
        #[inline]
        fn goto19_ctx11_x<'s>(lex: &mut Lexer<'s>) {
            match lex.read::<&[u8; 3usize]>() {
                Some([128u8..=143u8, 128u8..=191u8, 128u8..=191u8]) => {
                    lex.bump_unchecked(3usize);
                    goto2_ctx11_x(lex)
                }
                _ => goto11_ctx11_x(lex),
            }
        }
        #[inline]
        fn goto13_ctx11_x<'s>(lex: &mut Lexer<'s>) {
            match lex.read::<&[u8; 1usize]>() {
                Some([128u8..=191u8]) => {
                    lex.bump_unchecked(1usize);
                    goto2_ctx11_x(lex)
                }
                _ => goto11_ctx11_x(lex),
            }
        }
        #[inline]
        fn goto2_x<'s>(lex: &mut Lexer<'s>) { lex.set(Ok(Token::AnyUnicode)); }
        #[inline]
        fn goto20<'s>(lex: &mut Lexer<'s>) {
            enum Jump { J18, J1, J17, J11, J16, J15, J14, J19, J13, J2 }
            const LUT: [Jump; 256] = {
                use Jump::*;
                [J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J1, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J14, J15, J15, J15, J15, J15, J15, J15, J15, J15, J15, J15, J15, J16, J15, J15, J17, J18, J18, J18, J19, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11]
            };
            let byte = match lex.read::<u8>() {
                Some(byte) => byte,
                None => return _end(lex),
            };
            match LUT[byte as usize] {
                Jump::J18 => {
                    lex.bump_unchecked(1usize);
                    goto18_ctx11_x(lex)
                }
                Jump::J1 => {
                    lex.bump_unchecked(1usize);
                    goto1_x(lex)
                }
                Jump::J17 => {
                    lex.bump_unchecked(1usize);
                    goto17_ctx11_x(lex)
                }
                Jump::J11 => {
                    lex.bump_unchecked(1usize);
                    goto11_x(lex)
                }
                Jump::J16 => {
                    lex.bump_unchecked(1usize);
                    goto16_ctx11_x(lex)
                }
                Jump::J15 => {
                    lex.bump_unchecked(1usize);
                    goto15_ctx11_x(lex)
                }
                Jump::J14 => {
                    lex.bump_unchecked(1usize);
                    goto14_ctx11_x(lex)
                }
                Jump::J19 => {
                    lex.bump_unchecked(1usize);
                    goto19_ctx11_x(lex)
                }
                Jump::J13 => {
                    lex.bump_unchecked(1usize);
                    goto13_ctx11_x(lex)
                }
                Jump::J2 => { lex.bump_unchecked(1usize) ; goto2_x (lex) }
} } goto20 (lex) } }
right
impl<'s> ::logos::Logos<'s> for Token {
    type Error = ();
    type Extras = ();
    type Source = [u8];
    fn lex(lex: &mut ::logos::Lexer<'s, Self>) {
        use ::logos::internal::{LexerInternal, CallbackResult};
        type Lexer<'s> = ::logos::Lexer<'s, Token>;
        fn _end<'s>(lex: &mut Lexer<'s>) { lex.end() }
        fn _error<'s>(lex: &mut Lexer<'s>) {
            lex.bump_unchecked(1);
            lex.error();
        } macro_rules! _fast_loop { ($ lex : ident , $ test : ident , $ miss : expr) => { while let Some (arr) = $ lex . read :: < & [u8 ; 16] > () { if $ test (arr [0]) { if $ test (arr [1]) { if $ test (arr [2]) { if $ test (arr [3]) { if $ test (arr [4]) { if $ test (arr [5]) { if $ test (arr [6]) { if $ test (arr [7]) { if $ test (arr [8]) { if $ test (arr [9]) { if $ test (arr [10]) { if $ test (arr [11]) { if $ test (arr [12]) { if $ test (arr [13]) { if $ test (arr [14]) { if $ test (arr [15]) { $ lex . bump_unchecked (16) ; continue ; } $ lex . bump_unchecked (15) ; return $ miss ; } $ lex . bump_unchecked (14) ; return $ miss ; } $ lex . bump_unchecked (13) ; return $ miss ; } $ lex . bump_unchecked (12) ; return $ miss ; } $ lex . bump_unchecked (11) ; return $ miss ; } $ lex . bump_unchecked (10) ; return $ miss ; } $ lex . bump_unchecked (9) ; return $ miss ; } $ lex . bump_unchecked (8) ; return $ miss ; } $ lex . bump_unchecked (7) ; return $ miss ; } $ lex . bump_unchecked (6) ; return $ miss ; } $ lex . bump_unchecked (5) ; return $ miss ; } $ lex . bump_unchecked (4) ; return $ miss ; } $ lex . bump_unchecked (3) ; return $ miss ; } $ lex . bump_unchecked (2) ; return $ miss ; } $ lex . bump_unchecked (1) ; return $ miss ; } return $ miss ; } while $ lex . test ($ test) { $ lex . bump_unchecked (1) ; } $ miss } ; } #[inline]
        fn goto1_x<'s>(lex: &mut Lexer<'s>) { lex.set(Ok(Token::Newline)); }
        #[inline]
        fn goto11_ctx11_x<'s>(lex: &mut Lexer<'s>) { lex.set(Ok(Token::Any)); }
        #[inline]
        fn goto2_ctx11_x<'s>(lex: &mut Lexer<'s>) { lex.set(Ok(Token::AnyUnicode)); }
        #[inline]
        fn goto16_ctx11_x<'s>(lex: &mut Lexer<'s>) {
            match lex.read::<&[u8; 2usize]>() {
                Some([128u8..=159u8, 128u8..=191u8]) => {
                    lex.bump_unchecked(2usize);
                    goto2_ctx11_x(lex)
                }
                _ => goto11_ctx11_x(lex),
            }
        }
        #[inline]
        fn goto17_ctx11_x<'s>(lex: &mut Lexer<'s>) {
            match lex.read::<&[u8; 3usize]>() {
                Some([144u8..=191u8, 128u8..=191u8, 128u8..=191u8]) => {
                    lex.bump_unchecked(3usize);
                    goto2_ctx11_x(lex)
                }
                _ => goto11_ctx11_x(lex),
            }
        }
        #[inline]
        fn goto2_x<'s>(lex: &mut Lexer<'s>) { lex.set(Ok(Token::AnyUnicode)); }
        #[inline]
        fn goto13_ctx11_x<'s>(lex: &mut Lexer<'s>) {
            match lex.read::<&[u8; 1usize]>() {
                Some([128u8..=191u8]) => {
                    lex.bump_unchecked(1usize);
                    goto2_ctx11_x(lex)
                }
                _ => goto11_ctx11_x(lex),
            }
        }
        #[inline]
        fn goto18_ctx11_x<'s>(lex: &mut Lexer<'s>) {
            match lex.read::<&[u8; 3usize]>() {
                Some([128u8..=191u8, 128u8..=191u8, 128u8..=191u8]) => {
                    lex.bump_unchecked(3usize);
                    goto2_ctx11_x(lex)
                }
                _ => goto11_ctx11_x(lex),
            }
        }
        #[inline]
        fn goto15_ctx11_x<'s>(lex: &mut Lexer<'s>) {
            match lex.read::<&[u8; 2usize]>() {
                Some([128u8..=191u8, 128u8..=191u8]) => {
                    lex.bump_unchecked(2usize);
                    goto2_ctx11_x(lex)
                }
                _ => goto11_ctx11_x(lex),
            }
        }
        #[inline]
        fn goto14_ctx11_x<'s>(lex: &mut Lexer<'s>) {
            match lex.read::<&[u8; 2usize]>() {
                Some([160u8..=191u8, 128u8..=191u8]) => {
                    lex.bump_unchecked(2usize);
                    goto2_ctx11_x(lex)
                }
                _ => goto11_ctx11_x(lex),
            }
        }
        #[inline]
        fn goto19_ctx11_x<'s>(lex: &mut Lexer<'s>) {
            match lex.read::<&[u8; 3usize]>() {
                Some([128u8..=143u8, 128u8..=191u8, 128u8..=191u8]) => {
                    lex.bump_unchecked(3usize);
                    goto2_ctx11_x(lex)
                }
                _ => goto11_ctx11_x(lex),
            }
        }
        #[inline]
        fn goto11_x<'s>(lex: &mut Lexer<'s>) { lex.set(Ok(Token::Any)); }
        #[inline]
        fn goto20<'s>(lex: &mut Lexer<'s>) {
            enum Jump { J1, J16, J17, J2, J13, J18, J15, J14, J19, J11 }
            const LUT: [Jump; 256] = {
                use Jump::*;
                [J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J1, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J2, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J13, J14, J15, J15, J15, J15, J15, J15, J15, J15, J15, J15, J15, J15, J16, J15, J15, J17, J18, J18, J18, J19, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11, J11]
            };
            let byte = match lex.read::<u8>() {
                Some(byte) => byte,
                None => return _end(lex),
            };
            match LUT[byte as usize] {
                Jump::J1 => {
                    lex.bump_unchecked(1usize);
                    goto1_x(lex)
                }
                Jump::J16 => {
                    lex.bump_unchecked(1usize);
                    goto16_ctx11_x(lex)
                }
                Jump::J17 => {
                    lex.bump_unchecked(1usize);
                    goto17_ctx11_x(lex)
                }
                Jump::J2 => {
                    lex.bump_unchecked(1usize);
                    goto2_x(lex)
                }
                Jump::J13 => {
                    lex.bump_unchecked(1usize);
                    goto13_ctx11_x(lex)
                }
                Jump::J18 => {
                    lex.bump_unchecked(1usize);
                    goto18_ctx11_x(lex)
                }
                Jump::J15 => {
                    lex.bump_unchecked(1usize);
                    goto15_ctx11_x(lex)
                }
                Jump::J14 => {
                    lex.bump_unchecked(1usize);
                    goto14_ctx11_x(lex)
                }
                Jump::J19 => {
                    lex.bump_unchecked(1usize);
                    goto19_ctx11_x(lex)
                }
                Jump::J11 => { lex.bump_unchecked(1usize) ; goto11_x (lex) }
} } goto20 (lex) } }

I am not sure what to make of it, could someone advise on this? Other architectures worked fine, and the main difference with s390x is that it is big-endian

build.log

@jeertmans
Copy link
Collaborator

Looks like an interesting, but probably challenging bug!

do you have any other big-endian architecture you could test on to ensure the issue is endianess?

@LecrisUT
Copy link
Contributor Author

LecrisUT commented Oct 8, 2024

Unfortunately not in Fedora builders, those are only x86_64, aarch64, i686, s390x, ppc64le. Except for ppc64le which got canceled before running, all the other architectures ran successfully and all of them are little endian. I could help set up a builder for s390x and test with and without vendored dependencies to at least test that that is not a source of issue. The easiest and least invasive way that I can provide is to create a separate repo with all the CI configuration to run on s390x and then if you can work with patch files, than you could have full access to the builder.

@jeertmans
Copy link
Collaborator

I you can find a github runner or docker image that runs big endian and create a PR that adds a workflow on that architecture, that would greatly help reproducing your error :)

@LecrisUT
Copy link
Contributor Author

LecrisUT commented Oct 8, 2024

Maybe can try out with https://github.com/uraimo/run-on-arch-action?

@jeertmans
Copy link
Collaborator

Yes this looks like a good direction! Would you have time to work on a PR?

@LecrisUT
Copy link
Contributor Author

LecrisUT commented Oct 9, 2024

Using the GH Action wasn't really successful: #428. But I did manage to provide another reproducible environment using podman (might work with docker also) when running locally, so maybe that would also help?

@jeertmans
Copy link
Collaborator

I guess any runner / docker image with big-endian arch should be fine :-)
I am not familiar with podman, so you probably know more than me!

@LecrisUT
Copy link
Contributor Author

LecrisUT commented Oct 9, 2024

podman is the equivalent of docker and often times the syntax is equivalent. Try out the following Containerfile:

FROM s390x/fedora:latest

RUN dnf install -y git cargo

RUN git clone https://github.com/maciejhirsz/logos /logos

WORKDIR /logos

CMD ["cargo", "test", "--workspace", "--verbose"]

with

$ docker build --platform linux/s390x -f ./Containerfile -t debug:logos-s390x
$ docker run --platform linux/s390x debug:logos-s390x

or

$ podman build --arch s390x -f ./Containerfile -t debug:logos-s390x
$ podman run --arch s390x debug:logos-s390x

I had issues with the docker one failing on building autocfg which we know shouldn't happen since Fedora builders work fine for that and I confirmed with podman that it doesn't fail there. I hope this issue is purely with the GH action and you would instead be able to work with a local docker container.

Another option we could try is the one from docker itself, which might work if we debug within the Containerfile itself. Would that work for you? (Nope, that did not work either, with the same issues)
https://docs.docker.com/build/ci/github-actions/multi-platform/

@jeertmans
Copy link
Collaborator

Thanks for your investigation!

A small question I should have asked from the start:

Hi, I am updating logos to 0.14.2 on Fedora, when I've encountered the following issue when building for s390x:

Is this problem present with earlier versions of Logos?

I also see that you link

https://docs.docker.com/build/ci/github-actions/multi-platform/

Did you already give it a try?

@LecrisUT
Copy link
Contributor Author

It actually passed in 0.13.0. I haven't tested the other ones though.

Did you already give it a try?

Yep, consistently the same error. I'll setup a copr builder in a bit

@jeertmans jeertmans added the bug Something isn't working label Oct 13, 2024
@jeertmans
Copy link
Collaborator

Could you check with 0.14.0, and 0.14.1? To better identify which version introduced the bug.

@LecrisUT
Copy link
Contributor Author

LecrisUT commented Oct 13, 2024

I can only check as low as 0.14.1 because before that the tests were not present. Iirc the error happened there as well, but I'll double check tomorrow (checked and confirmed it was still an issue with 0.14.1).

@0x2a-42
Copy link
Contributor

0x2a-42 commented Oct 14, 2024

As far as I can tell, the only difference between result and reference is the order of functions, enumerators, and match branches. The output depends on the iteration order of a HashMap.

let branches = targets
.into_iter()
.enumerate()
.map(|(idx, (id, ranges))| {
let idx = (idx as u8) + 1;
let next = self.goto(id, ctx.advance(1));
jumps.push(format!("J{}", id).to_ident());
for byte in ranges.into_iter().flatten() {
table[byte as usize] = idx;
}
let jump = jumps.last().unwrap();
quote!(Jump::#jump => #next,)
})
.collect::<TokenStream>();

type Targets = Map<NodeId, Vec<Range>>;

use fnv::FnvHashMap as Map;

The key type uses the default Hash implementation of NonZeroU32

#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct NodeId(NonZeroU32);

which in turn uses the same Hash implementation as u32.
https://github.com/rust-lang/rust/blob/17a19e684cdf3ca088af8b4da6a6209d128913f4/library/core/src/num/nonzero.rs#L260

The Hash implementation of u32 calls write_u32 on the provided Hasher
https://github.com/rust-lang/rust/blob/17a19e684cdf3ca088af8b4da6a6209d128913f4/library/core/src/hash/mod.rs#L835
and the Hasher implementation of FnvHasher
https://github.com/servo/rust-fnv/blob/4e55052a343a4372c191141f29a17ab829cf1dbc/lib.rs#L115
uses the default implementation of the Hasher trait for this method
https://github.com/rust-lang/rust/blob/17a19e684cdf3ca088af8b4da6a6209d128913f4/library/core/src/hash/mod.rs#L375-L377
which turns the u32 into bytes by calling to_ne_bytes.

I guess the problem could be solved by providing a custom implementation of Hash for NodeId, which always uses to_le_bytes. Using a BTreeMap would also solve the problem, as it provides guarantees for its iteration order.

If the performance impact of these solutions is not acceptable, it would be possible to adjust the test, such that there are different references for big-endian and little-endian platforms.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants