Skip to content

Commit

Permalink
Merge pull request #5207 from wasmerio/5196-fix-llvm-relocations-and-…
Browse files Browse the repository at this point in the history
…simd-operations-on-aarch64

Fix(LLVM): Implement the missing relocations on aarch64, fix SIMD operations
  • Loading branch information
xdoardo authored Oct 31, 2024
2 parents f706fc8 + d83353f commit 597b108
Show file tree
Hide file tree
Showing 10 changed files with 186 additions and 80 deletions.
130 changes: 65 additions & 65 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ jobs:
target: aarch64-apple-darwin
artifact_name: 'wasmer-darwin-arm64'
use_sccache: false
use_llvm: false
use_llvm: true
build_wasm: false
# [todo] xdoardo: Reinstate when the code we generate for aarch64 is working correctly.
llvm_url: 'https://github.com/wasmerio/llvm-custom-builds/releases/download/18.x/llvm-darwin-aarch64.tar.xz'
Expand Down Expand Up @@ -573,70 +573,70 @@ jobs:
if-no-files-found: error
retention-days: 2

# linux_riscv64:
# name: Linux riscv64
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v3
# - uses: dtolnay/rust-toolchain@stable
# with:
# target: riscv64gc-unknown-linux-gnu
# - name: Build cross image
# run: |
# docker build -t wasmer/riscv64 ${GITHUB_WORKSPACE}/.github/cross-linux-riscv64/
# env:
# CROSS_DOCKER_IN_DOCKER: true
# - name: Build Wasmer binary
# run: |
# make build-wasmer
# env:
# CARGO_BINARY: docker run -v /var/run/docker.sock:/var/run/docker.sock -v ${GITHUB_WORKSPACE}:/project -w /project wasmer/riscv64:latest cargo
# CROSS_DOCKER_IN_DOCKER: true
# CARGO_TARGET: riscv64gc-unknown-linux-gnu
# PKG_CONFIG_PATH: /usr/lib/riscv64-linux-gnu/pkgconfig
# PKG_CONFIG_ALLOW_CROSS: true
# ENABLE_LLVM: 0
# - name: Build C API headless
# shell: bash
# run: |
# make package-capi-headless
# env:
# CARGO_BINARY: docker run -v /var/run/docker.sock:/var/run/docker.sock -v ${GITHUB_WORKSPACE}:/project -w /project wasmer/riscv64:latest cargo
# CROSS_DOCKER_IN_DOCKER: true
# CARGO_TARGET: riscv64gc-unknown-linux-gnu
# PKG_CONFIG_PATH: /usr/lib/riscv64-linux-gnu/pkgconfig
# PKG_CONFIG_ALLOW_CROSS: true
# ENABLE_LLVM: 0
# TARGET: riscv64gc-unknown-linux-gnu
# TARGET_DIR: target/riscv64gc-unknown-linux-gnu/release
# - name: Build C API
# run: |
# make build-capi
# env:
# CARGO_BINARY: docker run -v /var/run/docker.sock:/var/run/docker.sock -v ${GITHUB_WORKSPACE}:/project -w /project wasmer/riscv64:latest cargo
# CROSS_DOCKER_IN_DOCKER: true
# CARGO_TARGET: riscv64gc-unknown-linux-gnu
# PKG_CONFIG_PATH: /usr/lib/riscv64-linux-gnu/pkgconfig
# PKG_CONFIG_ALLOW_CROSS: true
# ENABLE_LLVM: 0
# - name: Dist
# run: |
# make distribution
# env:
# CARGO_BINARY: docker run -v /var/run/docker.sock:/var/run/docker.sock -v ${GITHUB_WORKSPACE}:/project -w /project wasmer/riscv64:latest cargo
# CROSS_DOCKER_IN_DOCKER: true
# CARGO_TARGET: riscv64gc-unknown-linux-gnu
# PKG_CONFIG_PATH: /usr/lib/riscv64-linux-gnu/pkgconfig
# PKG_CONFIG_ALLOW_CROSS: true
# TARGET: riscv64gc-unknown-linux-gnu
# TARGET_DIR: target/riscv64gc-unknown-linux-gnu/release
# - name: Upload Artifacts
# uses: actions/upload-artifact@v4
# with:
# name: wasmer-linux-riscv64
# path: dist
# if-no-files-found: error
# retention-days: 2
linux_riscv64:
name: Linux riscv64
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@stable
with:
target: riscv64gc-unknown-linux-gnu
- name: Build cross image
run: |
docker build -t wasmer/riscv64 ${GITHUB_WORKSPACE}/.github/cross-linux-riscv64/
env:
CROSS_DOCKER_IN_DOCKER: true
- name: Build Wasmer binary
run: |
make build-wasmer
env:
CARGO_BINARY: docker run -v /var/run/docker.sock:/var/run/docker.sock -v ${GITHUB_WORKSPACE}:/project -w /project wasmer/riscv64:latest cargo
CROSS_DOCKER_IN_DOCKER: true
CARGO_TARGET: riscv64gc-unknown-linux-gnu
PKG_CONFIG_PATH: /usr/lib/riscv64-linux-gnu/pkgconfig
PKG_CONFIG_ALLOW_CROSS: true
ENABLE_LLVM: 0
- name: Build C API headless
shell: bash
run: |
make package-capi-headless
env:
CARGO_BINARY: docker run -v /var/run/docker.sock:/var/run/docker.sock -v ${GITHUB_WORKSPACE}:/project -w /project wasmer/riscv64:latest cargo
CROSS_DOCKER_IN_DOCKER: true
CARGO_TARGET: riscv64gc-unknown-linux-gnu
PKG_CONFIG_PATH: /usr/lib/riscv64-linux-gnu/pkgconfig
PKG_CONFIG_ALLOW_CROSS: true
ENABLE_LLVM: 0
TARGET: riscv64gc-unknown-linux-gnu
TARGET_DIR: target/riscv64gc-unknown-linux-gnu/release
- name: Build C API
run: |
make build-capi
env:
CARGO_BINARY: docker run -v /var/run/docker.sock:/var/run/docker.sock -v ${GITHUB_WORKSPACE}:/project -w /project wasmer/riscv64:latest cargo
CROSS_DOCKER_IN_DOCKER: true
CARGO_TARGET: riscv64gc-unknown-linux-gnu
PKG_CONFIG_PATH: /usr/lib/riscv64-linux-gnu/pkgconfig
PKG_CONFIG_ALLOW_CROSS: true
ENABLE_LLVM: 0
- name: Dist
run: |
make distribution
env:
CARGO_BINARY: docker run -v /var/run/docker.sock:/var/run/docker.sock -v ${GITHUB_WORKSPACE}:/project -w /project wasmer/riscv64:latest cargo
CROSS_DOCKER_IN_DOCKER: true
CARGO_TARGET: riscv64gc-unknown-linux-gnu
PKG_CONFIG_PATH: /usr/lib/riscv64-linux-gnu/pkgconfig
PKG_CONFIG_ALLOW_CROSS: true
TARGET: riscv64gc-unknown-linux-gnu
TARGET_DIR: target/riscv64gc-unknown-linux-gnu/release
- name: Upload Artifacts
uses: actions/upload-artifact@v4
with:
name: wasmer-linux-riscv64
path: dist
if-no-files-found: error
retention-days: 2

release:
# needs: [setup, build, linux_aarch64, windows_gnu, linux_riscv64]
Expand Down
6 changes: 2 additions & 4 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -511,8 +511,7 @@ jobs:
os: macos-14,
target: aarch64-apple-darwin,
exe: '',
# [todo] xdoardo: Reinstate when the code we generate for aarch64 is working correctly.
# llvm_url: 'https://github.com/wasmerio/llvm-custom-builds/releases/download/18.x/llvm-darwin-aarch64.tar.xz'
llvm_url: 'https://github.com/wasmerio/llvm-custom-builds/releases/download/18.x/llvm-darwin-aarch64.tar.xz'
},
{
build: windows-x64,
Expand Down Expand Up @@ -765,8 +764,7 @@ jobs:
os: macos-14,
target: aarch64-apple-darwin,
exe: '',
# [todo] xdoardo: Reinstate when the code we generate for aarch64 is working correctly.
# llvm_url: 'https://github.com/wasmerio/llvm-custom-builds/releases/download/18.x/llvm-darwin-aarch64.tar.xz'
llvm_url: 'https://github.com/wasmerio/llvm-custom-builds/releases/download/18.x/llvm-darwin-aarch64.tar.xz'
},
{
build: windows-x64,
Expand Down
4 changes: 2 additions & 2 deletions examples/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ fn main() -> anyhow::Result<()> {
// see how we can do that:
println!("Growing memory...");

// 'wasm-c-api' does not support direct calls to memory.grow()
#[cfg(not(feature = "wasm-c-api"))]
// 'wamr' does not support direct calls to memory.grow()
#[cfg(not(feature = "wamr"))]
{
// Here we are requesting two more pages for our memory.
memory.grow(&mut store, 2)?;
Expand Down
1 change: 0 additions & 1 deletion examples/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,6 @@ fn main() -> anyhow::Result<()> {

// This test is currently failing with:
// not implemented: Native function definitions can't be directly called from the host yet
#[cfg(FALSE)]
#[test]
fn test_table() -> anyhow::Result<()> {
main()
Expand Down
2 changes: 2 additions & 0 deletions lib/compiler-llvm/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,13 @@ impl LLVM {
// but not in the case of Aarch64, there the ABI is slightly different
#[allow(clippy::match_single_binding)]
match target.triple().architecture {
Architecture::Aarch64(_) => wasmer_types::OperatingSystem::Darwin,
_ => wasmer_types::OperatingSystem::Linux,
}
} else {
target.triple().operating_system
};

let binary_format = if self.is_pic {
target.triple().binary_format
} else {
Expand Down
26 changes: 26 additions & 0 deletions lib/compiler-llvm/src/object_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,32 @@ where
object::RelocationKind::Elf(object::elf::R_LARCH_ABS64_LO20),
0,
) => RelocationKind::LArchAbs64Lo20,
(
object::Architecture::Aarch64,
object::RelocationKind::Elf(object::elf::R_AARCH64_ADR_PREL_LO21),
0,
) => RelocationKind::Aarch64AdrPrelLo21,
(
object::Architecture::Aarch64,
object::RelocationKind::Elf(object::elf::R_AARCH64_ADR_PREL_PG_HI21),
0,
) => RelocationKind::Aarch64AdrPrelPgHi21,
(
object::Architecture::Aarch64,
object::RelocationKind::Elf(object::elf::R_AARCH64_LDST128_ABS_LO12_NC),
0,
) => RelocationKind::Aarch64Ldst128AbsLo12Nc,
(
object::Architecture::Aarch64,
object::RelocationKind::Elf(object::elf::R_AARCH64_ADD_ABS_LO12_NC),
0,
) => RelocationKind::Aarch64AddAbsLo12Nc,
(
object::Architecture::Aarch64,
object::RelocationKind::Elf(object::elf::R_AARCH64_LDST64_ABS_LO12_NC),
0,
) => RelocationKind::Aarch64Ldst64AbsLo12Nc,

_ => {
return Err(CompileError::Codegen(format!(
"unknown relocation {:?}",
Expand Down
4 changes: 0 additions & 4 deletions lib/compiler-llvm/src/translator/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1104,10 +1104,6 @@ impl<'ctx> Intrinsics<'ctx> {
intrinsics
.throw_trap
.add_attribute(AttributeLoc::Function, noreturn);
//intrinsics
// .func_ref
// .add_attribute(AttributeLoc::Function, intrinsics.readonly);

intrinsics
}
}
Expand Down
53 changes: 53 additions & 0 deletions lib/compiler/src/engine/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,59 @@ fn apply_relocation(
| read_unaligned(reloc_address as *mut u32);
write_unaligned(reloc_address as *mut u32, reloc_abs);
},
RelocationKind::Aarch64AdrPrelPgHi21 => unsafe {
let (reloc_address, delta) = r.for_address(body, target_func_address as u64);

let delta = delta as isize;
assert!(
((-1 << 32)..(1 << 32)).contains(&delta),
"can't generate page-relative relocation with ±4GB `adrp` instruction"
);

let op = read_unaligned(reloc_address as *mut u32);
let delta = delta >> 12;
let immlo = ((delta as u32) & 0b11) << 29;
let immhi = (((delta as u32) >> 2) & 0x7ffff) << 5;
let mask = !((0x7ffff << 5) | (0b11 << 29));
let op = (op & mask) | immlo | immhi;

write_unaligned(reloc_address as *mut u32, op);
},
RelocationKind::Aarch64AdrPrelLo21 => unsafe {
let (reloc_address, delta) = r.for_address(body, target_func_address as u64);

let delta = delta as isize;
assert!(
((-1 << 20)..(1 << 20)).contains(&delta),
"can't generate an ADR_PREL_LO21 relocation with an immediate larger than 20 bits"
);

let op = read_unaligned(reloc_address as *mut u32);
let immlo = ((delta as u32) & 0b11) << 29;
let immhi = (((delta as u32) >> 2) & 0x7ffff) << 5;
let mask = !((0x7ffff << 5) | (0b11 << 29));
let op = (op & mask) | immlo | immhi;

write_unaligned(reloc_address as *mut u32, op);
},
RelocationKind::Aarch64AddAbsLo12Nc => unsafe {
let (reloc_address, reloc_delta) = r.for_address(body, target_func_address as u64);
let reloc_delta = (reloc_delta as u32 & 0xfff)
| (read_unaligned(reloc_address as *mut u32) & 0xFFC003FF);
write_unaligned(reloc_address as *mut u32, reloc_delta);
},
RelocationKind::Aarch64Ldst128AbsLo12Nc => unsafe {
let (reloc_address, reloc_delta) = r.for_address(body, target_func_address as u64);
let reloc_delta = ((reloc_delta as u32 & 0xfff) >> 4) << 10
| (read_unaligned(reloc_address as *mut u32) & 0xFFC003FF);
write_unaligned(reloc_address as *mut u32, reloc_delta);
},
RelocationKind::Aarch64Ldst64AbsLo12Nc => unsafe {
let (reloc_address, reloc_delta) = r.for_address(body, target_func_address as u64);
let reloc_delta = ((reloc_delta as u32 & 0xfff) >> 3) << 10
| (read_unaligned(reloc_address as *mut u32) & 0xFFC003FF);
write_unaligned(reloc_address as *mut u32, reloc_delta);
},
kind => panic!(
"Relocation kind unsupported in the current architecture {}",
kind
Expand Down
37 changes: 35 additions & 2 deletions lib/types/src/compilation/relocation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,22 @@ pub enum RelocationKind {
X86CallPLTRel4,
/// x86 GOT PC-relative 4-byte
X86GOTPCRel4,

/// R_AARCH64_ADR_PREL_LO21
Aarch64AdrPrelLo21,

/// R_AARCH64_ADR_PREL_PG_HI21
Aarch64AdrPrelPgHi21,

/// R_AARCH64_ADD_ABS_LO12_NC
Aarch64AddAbsLo12Nc,

/// R_AARCH64_LDST128_ABS_LO12_NC
Aarch64Ldst128AbsLo12Nc,

/// R_AARCH64_LDST64_ABS_LO12_NC
Aarch64Ldst64AbsLo12Nc,

/// Arm32 call target
Arm32Call,
/// Arm64 call target
Expand Down Expand Up @@ -102,6 +118,11 @@ impl fmt::Display for RelocationKind {
Self::LArchAbsLo12 => write!(f, "LArchAbsLo12"),
Self::LArchAbs64Hi12 => write!(f, "LArchAbs64Hi12"),
Self::LArchAbs64Lo20 => write!(f, "LArchAbs64Lo20"),
Self::Aarch64AdrPrelLo21 => write!(f, "Aarch64AdrPrelLo21"),
Self::Aarch64AdrPrelPgHi21 => write!(f, "Aarch64AdrPrelPgHi21"),
Self::Aarch64AddAbsLo12Nc => write!(f, "Aarch64AddAbsLo12Nc"),
Self::Aarch64Ldst128AbsLo12Nc => write!(f, "Aarch64Ldst128AbsLo12Nc"),
Self::Aarch64Ldst64AbsLo12Nc => write!(f, "Aarch64Ldst64AbsLo12Nc"),
// Self::MachOX86_64Tlv => write!(f, "MachOX86_64Tlv"),
}
}
Expand Down Expand Up @@ -142,7 +163,10 @@ pub trait RelocationLike {
| RelocationKind::Arm64Movw1
| RelocationKind::Arm64Movw2
| RelocationKind::Arm64Movw3
| RelocationKind::RiscvPCRelLo12I => {
| RelocationKind::RiscvPCRelLo12I
| RelocationKind::Aarch64AddAbsLo12Nc
| RelocationKind::Aarch64Ldst128AbsLo12Nc
| RelocationKind::Aarch64Ldst64AbsLo12Nc => {
let reloc_address = start + self.offset() as usize;
let reloc_addend = self.addend() as isize;
let reloc_abs = target_func_address
Expand Down Expand Up @@ -178,14 +202,23 @@ pub trait RelocationLike {
}
RelocationKind::Arm64Call
| RelocationKind::RiscvCall
| RelocationKind::RiscvPCRelHi20 => {
| RelocationKind::RiscvPCRelHi20
| RelocationKind::Aarch64AdrPrelLo21 => {
let reloc_address = start + self.offset() as usize;
let reloc_addend = self.addend() as isize;
let reloc_delta_u32 = target_func_address
.wrapping_sub(reloc_address as u64)
.wrapping_add(reloc_addend as u64);
(reloc_address, reloc_delta_u32)
}
RelocationKind::Aarch64AdrPrelPgHi21 => {
let reloc_address = start + self.offset() as usize;
let reloc_addend = self.addend() as isize;
let target_page =
(target_func_address.wrapping_add(reloc_addend as u64) & !(0xFFF)) as usize;
let pc_page = reloc_address & !(0xFFF);
(reloc_address, target_page.wrapping_sub(pc_page) as u64)
}
_ => panic!("Relocation kind unsupported"),
}
}
Expand Down
3 changes: 1 addition & 2 deletions tests/compilers/artifact.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use std::{fs, path::PathBuf};

use cfg_if::cfg_if;
use wasmer::{Engine, Module};

#[test]
Expand Down Expand Up @@ -57,6 +55,7 @@ fn artifact_serialization_build() {
#[test]
#[cfg(target_arch = "x86_64")]
fn artifact_deserialization_roundtrip() {
use cfg_if::cfg_if;
// This test is included to make sure we don't break the serialized format
// by mistake. Otherwise, everything in this test is already tested in
// `artifact_serialization_roundtrip`.
Expand Down

0 comments on commit 597b108

Please sign in to comment.