From 2e0f983ccfbed6f8879ee7d5dbb8446068ee82ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BF=A0=20/=20green?= Date: Tue, 9 Apr 2024 15:16:09 +0900 Subject: [PATCH] feat(target): add support for s390x-unknown-linux-gnu (#2028) * feat(target): add support for s390x-unknown-linux-gnu * chore: rerun CI --- .github/workflows/test-release.yaml | 10 ++++++ cli/src/api/templates/ci-template.ts | 6 ++++ .../__tests__/__snapshots__/target.spec.ts.md | 7 ++++ .../__snapshots__/target.spec.ts.snap | Bin 1271 -> 1314 bytes cli/src/utils/target.ts | 2 ++ .../src/bindgen_runtime/js_values/bigint.rs | 33 ++++++++++++------ crates/napi/src/env.rs | 20 +++++++++-- crates/napi/src/js_values/bigint.rs | 33 ++++++++++++------ crates/napi/src/js_values/ser.rs | 16 ++------- 9 files changed, 90 insertions(+), 37 deletions(-) diff --git a/.github/workflows/test-release.yaml b/.github/workflows/test-release.yaml index 906062c6..12beda75 100644 --- a/.github/workflows/test-release.yaml +++ b/.github/workflows/test-release.yaml @@ -249,6 +249,10 @@ jobs: setup: | sudo apt-get update sudo apt-get install -y gcc-powerpc64le-linux-gnu + - target: s390x-unknown-linux-gnu + setup: | + sudo apt-get update + sudo apt-get install -y gcc-s390x-linux-gnu steps: - uses: actions/checkout@v4 @@ -383,6 +387,12 @@ jobs: arch: 'ppc64' libc: 'gnu' without-lerna: true + - image: 'node:{:version}-slim' + target: s390x-unknown-linux-gnu + args: '--platform linux/s390x' + arch: 's390x' + libc: 'gnu' + without-lerna: true - image: 'node:{:version}-alpine' target: x86_64-unknown-linux-musl args: '' diff --git a/cli/src/api/templates/ci-template.ts b/cli/src/api/templates/ci-template.ts index 75fde639..f9750498 100644 --- a/cli/src/api/templates/ci-template.ts +++ b/cli/src/api/templates/ci-template.ts @@ -85,6 +85,12 @@ jobs: sudo apt-get update sudo apt-get install gcc-powerpc64le-linux-gnu -y build: ${packageManager} build --platform --target powerpc64le-unknown-linux-gnu + - host: ubuntu-latest + target: 's390x-unknown-linux-gnu' + setup: | + sudo apt-get update + sudo apt-get install gcc-s390x-linux-gnu -y + build: ${packageManager} build --platform --target s390x-unknown-linux-gnu - host: ubuntu-latest target: 'wasm32-wasi-preview1-threads' build: ${packageManager} build --platform --target wasm32-wasi-preview1-threads diff --git a/cli/src/utils/__tests__/__snapshots__/target.spec.ts.md b/cli/src/utils/__tests__/__snapshots__/target.spec.ts.md index 6403f629..03e88728 100644 --- a/cli/src/utils/__tests__/__snapshots__/target.spec.ts.md +++ b/cli/src/utils/__tests__/__snapshots__/target.spec.ts.md @@ -128,6 +128,13 @@ Generated by [AVA](https://avajs.dev). platformArchABI: 'linux-ppc64-gnu', triple: 'powerpc64le-unknown-linux-gnu', }, + { + abi: 'gnu', + arch: 's390x', + platform: 'linux', + platformArchABI: 'linux-s390x-gnu', + triple: 's390x-unknown-linux-gnu', + }, { abi: 'wasi', arch: 'wasm32', diff --git a/cli/src/utils/__tests__/__snapshots__/target.spec.ts.snap b/cli/src/utils/__tests__/__snapshots__/target.spec.ts.snap index 3c8261cf497ddaf309f825ec1e931f593522e158..fcec5bf4ff74d785b91d3159fc1071ea9a7e7297 100644 GIT binary patch literal 1314 zcmV+-1>O2VRzV&-0$0nyl1HC;a(yPQz_foVl(3bgfw_Z?D^)?`&^)ZoT4c zFV#HHDK#o5UB7DA{pni6pFdkJ+YS5h=;;Us!AHbIp#eM%oC014-UQwT-UmJcz5u=h zegdun*MPr(n1H;1Z31=(*ezh6e5PlGHsN{pNg=w*G)+VTkw+wjcvQ&6lS0f35JJj} zfgF+Y_drIZ92)@+XU!I#TE`{cq9vxS$H`M?`7et zYO_MNEjhR?2NOAPa`0*nKF=w(Y{>R^4x)LuJr57(;Y1$J?!4bFR3!(9MtneXQDCJ(ngI9gxcG z>@Y}N3@@*6ZSHb4t0$_pR<*+?eSO%XGfltpAH!Ko;d-pE(B0CTu5Ij#=g*eb0I%g% zckLV$PX>4K!s{z|8@qV*QnBS$%e9u@ajm@4B6DlqHxiw`5l*b&shggd?ai#|TbN&*TgBxzpx|w_y_wku!zI@B_TfwfFYW&TTDT6n><$#tZM{gB zn)|(}LELH~hrBvkORkQ^9_xn&wM4w(?$~y%ysN~URd?3$d|T~ls~p!>XIw9rUhOZ7 zal_5+egn?%T)#BC#={`nK7mf^{)6t;PUNxD3T9p3yMMi2TA#bWOx&MtYrWQTydbvX ztOuXJYwvyP&ew!bChpI-u^qR9TT09JZ`x7xmhI2n*+%N&s# zSNK86rXPz400000000BUmQ9EoWf;eQ?4bmkU8mtTDo$t0U#K-J<>|WZ`Ob91bL$mn zx>WN#r_`vNbp5Jb_ZMmn|I|{sY&Yzqg+`17!AB%Tz7DijA6^7r1Kt9bfV05Iz9*P%WX%dY*k!h`urm1EC>uh_n!gM7VHT2v2|zq5L3_ z6QR5q$XF+h$V@2J zI0!wI4+b(D%0?iKP<|LlGn79D(hB}Fb(aEr6*#ECQwqGKz(-2Yzxw3dvrefYCf1~B znj!X!0>3MeQsGV&j;Qd8Dq*n*c20%!DqK<_mVnz6a4aEV@d$Q00cR4hyc&Kn0csK+ zN=ld#!P-f9J_+w6;qxT?w5q345~fD5BPlqV0)I91jTC&Ef?s7U5yAFoaH|FnYf#qU zRSmw-BrF-h{?g!z29s%cAPvXT@Mc=VQW5OSG<=hWKhluPz<~@@GZLmnu=g@>HUk$j z@N)*TI?U=4mX2U89iG$SZ5=+-VMT|@tb}DE*yC9^l7&tdPG?~`3zua~k6`y1aL54L zfKvv%Z@`KnVc7^aZNhCPJZi$c39ql}3#Nn_5$tahCM?)(!C?zr3zjSiGb7ly7JP5P z6$|#};E^1>kdrVgf_;*Mz0yMeL9xBXnf+2kvR<(p^EGd=|Akt%y|!DG!i;{{ ztXEo?J^Wbz`%E{wI4HH+?ezV}f*ovTW`EJH*DFr3zs!yHld!90ujZCVG^F>!M{#sh z-%-V_Hao?&g|25Q(8sIIt@~2KMMrdH^mZ5|E=HG^eC_J{YF1BFYwc>!U&syd7GG@o zmH*hBx!&A>^(A+cgWYw(q4xY%X&dad-RiyfjA}0o?%Rv5FWKAKw^uI}+ita7Yx_NF z^OY9sYwb?f+o3aMkFBJCL028RT?5JnT&k;DL>b4xux8z7*FJPfSv3G`AAA9T0$ zB9E6gG3$oj{peRr|3;5l~L{})%h#7wso001i(cYFW< diff --git a/cli/src/utils/target.ts b/cli/src/utils/target.ts index f120895c..fb58cba3 100644 --- a/cli/src/utils/target.ts +++ b/cli/src/utils/target.ts @@ -24,6 +24,7 @@ export const AVAILABLE_TARGETS = [ 'universal-apple-darwin', 'riscv64gc-unknown-linux-gnu', 'powerpc64le-unknown-linux-gnu', + 's390x-unknown-linux-gnu', 'wasm32-wasi-preview1-threads', ] as const @@ -40,6 +41,7 @@ export const TARGET_LINKER: Record = { 'aarch64-unknown-linux-musl': 'aarch64-linux-musl-gcc', 'riscv64gc-unknown-linux-gnu': 'riscv64-linux-gnu-gcc', 'powerpc64le-unknown-linux-gnu': 'powerpc64le-linux-gnu-gcc', + 's390x-unknown-linux-gnu': 's390x-linux-gnu-gcc', } // https://nodejs.org/api/process.html#process_process_arch diff --git a/crates/napi/src/bindgen_runtime/js_values/bigint.rs b/crates/napi/src/bindgen_runtime/js_values/bigint.rs index 5261e137..cd2da832 100644 --- a/crates/napi/src/bindgen_runtime/js_values/bigint.rs +++ b/crates/napi/src/bindgen_runtime/js_values/bigint.rs @@ -107,8 +107,7 @@ impl BigInt { if len == 1 { (self.words[0] as i128, false) } else { - let i128_words: [i64; 2] = [self.words[0] as _, self.words[1] as _]; - let mut val = unsafe { ptr::read(i128_words.as_ptr() as *const i128) }; + let mut val = self.words[0] as i128 + ((self.words[1] as i128) << 64); if self.sign_bit { val = -val; } @@ -125,8 +124,7 @@ impl BigInt { if len == 1 { (self.sign_bit, self.words[0] as u128, false) } else { - let u128_words: [u64; 2] = [self.words[0], self.words[1]]; - let val = unsafe { ptr::read(u128_words.as_ptr() as *const u128) }; + let val = self.words[0] as u128 + ((self.words[1] as u128) << 64); (self.sign_bit, val, len > 2) } } @@ -156,7 +154,16 @@ impl ToNapiValue for i128 { unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result { let mut raw_value = ptr::null_mut(); let sign_bit = i32::from(val <= 0); - let words = &val as *const i128 as *const u64; + if cfg!(target_endian = "little") { + let words = &val as *const i128 as *const u64; + check_status!(unsafe { + sys::napi_create_bigint_words(env, sign_bit, 2, words, &mut raw_value) + })?; + return Ok(raw_value); + } + + let arr: [u64; 2] = [val as _, (val >> 64) as _]; + let words = &arr as *const u64; check_status!(unsafe { sys::napi_create_bigint_words(env, sign_bit, 2, words, &mut raw_value) })?; @@ -167,7 +174,14 @@ impl ToNapiValue for i128 { impl ToNapiValue for u128 { unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result { let mut raw_value = ptr::null_mut(); - let words = &val as *const u128 as *const u64; + if cfg!(target_endian = "little") { + let words = &val as *const u128 as *const u64; + check_status!(unsafe { sys::napi_create_bigint_words(env, 0, 2, words, &mut raw_value) })?; + return Ok(raw_value); + } + + let arr: [u64; 2] = [val as _, (val >> 64) as _]; + let words = &arr as *const u64; check_status!(unsafe { sys::napi_create_bigint_words(env, 0, 2, words, &mut raw_value) })?; Ok(raw_value) } @@ -226,20 +240,19 @@ impl From for BigInt { impl From for BigInt { fn from(val: i128) -> Self { let sign_bit = val < 0; - let words = (if sign_bit { -val } else { val }).to_ne_bytes(); + let val = if sign_bit { -val } else { val }; BigInt { sign_bit, - words: unsafe { std::slice::from_raw_parts(words.as_ptr() as *mut _, 2).to_vec() }, + words: vec![val as _, (val >> 64) as _], } } } impl From for BigInt { fn from(val: u128) -> Self { - let words = val.to_ne_bytes(); BigInt { sign_bit: false, - words: unsafe { std::slice::from_raw_parts(words.as_ptr() as *mut _, 2).to_vec() }, + words: vec![val as _, (val >> 64) as _], } } } diff --git a/crates/napi/src/env.rs b/crates/napi/src/env.rs index 25cf5db8..b27e30c4 100644 --- a/crates/napi/src/env.rs +++ b/crates/napi/src/env.rs @@ -119,7 +119,16 @@ impl Env { pub fn create_bigint_from_i128(&self, value: i128) -> Result { let mut raw_value = ptr::null_mut(); let sign_bit = i32::from(value <= 0); - let words = &value as *const i128 as *const u64; + if cfg!(target_endian = "little") { + let words = &value as *const i128 as *const u64; + check_status!(unsafe { + sys::napi_create_bigint_words(self.0, sign_bit, 2, words, &mut raw_value) + })?; + return Ok(JsBigInt::from_raw_unchecked(self.0, raw_value, 2)); + } + + let arr: [u64; 2] = [value as _, (value >> 64) as _]; + let words = &arr as *const u64; check_status!(unsafe { sys::napi_create_bigint_words(self.0, sign_bit, 2, words, &mut raw_value) })?; @@ -129,7 +138,14 @@ impl Env { #[cfg(feature = "napi6")] pub fn create_bigint_from_u128(&self, value: u128) -> Result { let mut raw_value = ptr::null_mut(); - let words = &value as *const u128 as *const u64; + if cfg!(target_endian = "little") { + let words = &value as *const u128 as *const u64; + check_status!(unsafe { sys::napi_create_bigint_words(self.0, 0, 2, words, &mut raw_value) })?; + return Ok(JsBigInt::from_raw_unchecked(self.0, raw_value, 2)); + } + + let arr: [u64; 2] = [value as _, (value >> 64) as _]; + let words = &arr as *const u64; check_status!(unsafe { sys::napi_create_bigint_words(self.0, 0, 2, words, &mut raw_value) })?; Ok(JsBigInt::from_raw_unchecked(self.0, raw_value, 2)) } diff --git a/crates/napi/src/js_values/bigint.rs b/crates/napi/src/js_values/bigint.rs index a72b44b0..0e96dbf8 100644 --- a/crates/napi/src/js_values/bigint.rs +++ b/crates/napi/src/js_values/bigint.rs @@ -246,17 +246,22 @@ impl JsBigInt { pub fn get_i128(&mut self) -> Result<(i128, bool)> { let (signed, words) = self.get_words()?; - let high_part = words.first().copied().unwrap_or(0).to_le_bytes(); - let low_part = words.get(1).copied().unwrap_or(0).to_le_bytes(); + let low_part = words.first().copied().unwrap_or(0).to_ne_bytes(); + let high_part = words.get(1).copied().unwrap_or(0).to_ne_bytes(); let mut val = [0_u8; std::mem::size_of::()]; - - let (high_val, low_val) = val.split_at_mut(low_part.len()); + let high_val: &mut [u8]; + let low_val: &mut [u8]; + if cfg!(target_endian = "little") { + (low_val, high_val) = val.split_at_mut(low_part.len()); + } else { + (high_val, low_val) = val.split_at_mut(low_part.len()); + } high_val.copy_from_slice(&high_part); low_val.copy_from_slice(&low_part); - let mut val = i128::from_le_bytes(val); + let mut val = i128::from_ne_bytes(val); let mut loss = words.len() > 2; let mut overflow = false; @@ -275,17 +280,23 @@ impl JsBigInt { pub fn get_u128(&mut self) -> Result<(bool, u128, bool)> { let (signed, words) = self.get_words()?; - let high_part = words.first().copied().unwrap_or(0).to_le_bytes(); - let low_part = words.get(1).copied().unwrap_or(0).to_le_bytes(); + let low_part = words.first().copied().unwrap_or(0).to_ne_bytes(); + let high_part = words.get(1).copied().unwrap_or(0).to_ne_bytes(); - let mut val = [0_u8; std::mem::size_of::()]; - - let (high_val, low_val) = val.split_at_mut(low_part.len()); + let mut val = [0_u8; std::mem::size_of::()]; + let high_val: &mut [u8]; + let low_val: &mut [u8]; + if cfg!(target_endian = "little") { + (low_val, high_val) = val.split_at_mut(low_part.len()); + } else { + (high_val, low_val) = val.split_at_mut(low_part.len()); + } high_val.copy_from_slice(&high_part); low_val.copy_from_slice(&low_part); - let val = u128::from_le_bytes(val); + let val = u128::from_ne_bytes(val); + let len = words.len(); Ok((signed, val, len > 2)) diff --git a/crates/napi/src/js_values/ser.rs b/crates/napi/src/js_values/ser.rs index 9a53b2ba..42f4b3a1 100644 --- a/crates/napi/src/js_values/ser.rs +++ b/crates/napi/src/js_values/ser.rs @@ -1,6 +1,4 @@ use std::result::Result as StdResult; -#[cfg(feature = "napi6")] -use std::slice; use serde::{ser, Serialize, Serializer}; @@ -124,12 +122,7 @@ impl<'env> Serializer for Ser<'env> { #[cfg(feature = "napi6")] fn serialize_u128(self, v: u128) -> Result { - let words_ref = &v as *const _; - let words = unsafe { slice::from_raw_parts(words_ref as *const u64, 2) }; - self - .0 - .create_bigint_from_words(false, words.to_vec()) - .map(|v| v.raw) + self.0.create_bigint_from_u128(v).map(|v| v.raw) } #[cfg(all( @@ -147,12 +140,7 @@ impl<'env> Serializer for Ser<'env> { #[cfg(feature = "napi6")] fn serialize_i128(self, v: i128) -> Result { - let words_ref = &(v as u128) as *const _; - let words = unsafe { slice::from_raw_parts(words_ref as *const u64, 2) }; - self - .0 - .create_bigint_from_words(v < 0, words.to_vec()) - .map(|v| v.raw) + self.0.create_bigint_from_i128(v).map(|v| v.raw) } fn serialize_unit(self) -> Result {