Skip to content

Commit

Permalink
Merge pull request #5152 from wasmerio/loongarch64
Browse files Browse the repository at this point in the history
Experimental: add support for loongarch64 on LLVM
  • Loading branch information
xdoardo authored Oct 21, 2024
2 parents 7db446f + 2983132 commit 1bb7399
Show file tree
Hide file tree
Showing 14 changed files with 218 additions and 69 deletions.
11 changes: 1 addition & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 9 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ SHELL=/usr/bin/env bash
#
# Here is what works and what doesn't:
#
# * Cranelift works everywhere,
# * Cranelift works everywhere except */`loongarch64`,
#
# * LLVM works on Linux+Darwin/`amd64`,
# and linux+`aarch64`, linux+`riscv`
# and linux+`aarch64`, linux+`riscv`, linux+`loongarch64`
# but it doesn't work on Darwin/`aarch64` or Windows/`aarch64`.
#
# * Singlepass works on Linux+Darwin+Windows/`amd64`,
# and Linux+Darwin/`aarch64`
# it doesn't work on */`riscv`.
# it doesn't work on */`riscv` or */`loongarch64`.
#
# * Windows isn't tested on `aarch64`, that's why we consider it's not
# working, but it might possibly be.
Expand All @@ -48,6 +48,7 @@ IS_WINDOWS := 0
IS_AMD64 := 0
IS_AARCH64 := 0
IS_RISCV64 := 0
IS_LOONGARCH64 := 0

# Test Windows apart because it doesn't support `uname -s`.
ifeq ($(OS), Windows_NT)
Expand Down Expand Up @@ -80,11 +81,13 @@ else
IS_AARCH64 := 1
else ifneq (, $(filter $(uname), riscv64))
IS_RISCV64 := 1
else ifneq (, $(filter $(uname), loongarch64))
IS_LOONGARCH64 := 1
else
# We use spaces instead of tabs to indent `$(error)`
# otherwise it's considered as a command outside a
# target and it will fail.
$(error Unrecognized architecture, expect `x86_64`, `aarch64`, `arm64`, 'riscv64')
$(error Unrecognized architecture, expect `x86_64`, `aarch64`, `arm64`, 'riscv64', 'loongarch64')
endif

# Libc
Expand Down Expand Up @@ -241,6 +244,8 @@ ifeq ($(ENABLE_LLVM), 1)
compilers_engines += llvm-universal
else ifeq ($(IS_RISCV64), 1)
compilers_engines += llvm-universal
else ifeq ($(IS_LOONGARCH64), 1)
compilers_engines += llvm-universal
endif
endif
endif
Expand Down
5 changes: 3 additions & 2 deletions lib/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -252,21 +252,22 @@ clap = { version = "4.4.0", default-features = false, features = [
"env",
] }

[target.'cfg(not(target_arch = "riscv64"))'.dependencies]
[target.'cfg(not(any(target_arch = "riscv64", target_arch = "loongarch64")))'.dependencies]
reqwest = { workspace = true, default-features = false, features = [
"rustls-tls",
"json",
"multipart",
"gzip",
] }

[target.'cfg(target_arch = "riscv64")'.dependencies]
[target.'cfg(any(target_arch = "riscv64", target_arch = "loongarch64"))'.dependencies]
reqwest = { workspace = true, default-features = false, features = [
"native-tls",
"json",
"multipart",
] }


[build-dependencies]
chrono = { version = "^0.4", default-features = false, features = [
"std",
Expand Down
10 changes: 8 additions & 2 deletions lib/compiler-llvm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ wasmer-vm = { path = "../vm", version = "=5.0.0-rc.1" }
wasmer-types = { path = "../types", version = "=5.0.0-rc.1" }
target-lexicon = { version = "0.12.2", default-features = false }
smallvec = "1.6"
object = { version = "0.28.3", default-features = false, features = ["read"] }
object = { version = "0.30.3", default-features = false, features = ["read"] }
libc.workspace = true
byteorder = "1"
itertools = "0.10"
Expand All @@ -31,7 +31,13 @@ rayon = "1.5"
package = "inkwell"
version = "0.5.0"
default-features = false
features = ["llvm18-0-prefer-static", "target-x86", "target-aarch64", "target-riscv"]
features = [
"llvm18-0-prefer-static",
"target-x86",
"target-aarch64",
"target-riscv",
"target-loongarch",
]

[build-dependencies]
cc = "1.0"
Expand Down
12 changes: 12 additions & 0 deletions lib/compiler-llvm/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,16 @@ impl LLVM {
info: true,
machine_code: true,
}),
Architecture::LoongArch64 => {
InkwellTarget::initialize_loongarch(&InitializationConfig {
asm_parser: true,
asm_printer: true,
base: true,
disassembler: true,
info: true,
machine_code: true,
})
}
// Architecture::Arm(_) => InkwellTarget::initialize_arm(&InitializationConfig {
// asm_parser: true,
// asm_printer: true,
Expand All @@ -197,10 +207,12 @@ impl LLVM {
&target_triple,
match triple.architecture {
Architecture::Riscv64(_) => "generic-rv64",
Architecture::LoongArch64 => "generic-la64",
_ => "generic",
},
match triple.architecture {
Architecture::Riscv64(_) => "+m,+a,+c,+d,+f",
Architecture::LoongArch64 => "+f,+d",
_ => &llvm_cpu_features,
},
self.opt_level,
Expand Down
20 changes: 20 additions & 0 deletions lib/compiler-llvm/src/object_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,26 @@ where
object::RelocationKind::Elf(object::elf::R_RISCV_PCREL_LO12_I),
0,
) => RelocationKind::RiscvPCRelLo12I,
(
object::Architecture::LoongArch64,
object::RelocationKind::Elf(object::elf::R_LARCH_ABS_HI20),
0,
) => RelocationKind::LArchAbsHi20,
(
object::Architecture::LoongArch64,
object::RelocationKind::Elf(object::elf::R_LARCH_ABS_LO12),
0,
) => RelocationKind::LArchAbsLo12,
(
object::Architecture::LoongArch64,
object::RelocationKind::Elf(object::elf::R_LARCH_ABS64_HI12),
0,
) => RelocationKind::LArchAbs64Hi12,
(
object::Architecture::LoongArch64,
object::RelocationKind::Elf(object::elf::R_LARCH_ABS64_LO20),
0,
) => RelocationKind::LArchAbs64Lo20,
_ => {
return Err(CompileError::Codegen(format!(
"unknown relocation {:?}",
Expand Down
19 changes: 19 additions & 0 deletions lib/compiler/src/artifact_builders/trampoline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ const RISCV64_TRAMPOLINE: [u8; 24] = [
0, 0, 0, 0,
];

// PCADDI r12, 0 0c 00 00 18
// LD.D r12, r12, 16 8c 41 c0 28
// JR r12 80 01 00 4c [00 00 00 00]
// JMPADDR 00 00 00 00 00 00 00 00
const LOONGARCH64_TRAMPOLINE: [u8; 24] = [
0x0c, 0x00, 0x00, 0x0c, 0x8c, 0x41, 0xc0, 0x28, 0x80, 0x01, 0x00, 0x4c, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,
];

fn make_trampoline(
target: &Target,
libcall: LibCall,
Expand Down Expand Up @@ -70,6 +79,15 @@ fn make_trampoline(
addend: 0,
});
}
Architecture::LoongArch64 => {
code.extend(LOONGARCH64_TRAMPOLINE);
relocations.push(Relocation {
kind: RelocationKind::Abs8,
reloc_target: RelocationTarget::LibCall(libcall),
offset: code.len() as u32 - 8,
addend: 0,
});
}
arch => panic!("Unsupported architecture: {}", arch),
};
}
Expand All @@ -80,6 +98,7 @@ pub fn libcall_trampoline_len(target: &Target) -> usize {
Architecture::Aarch64(_) => AARCH64_TRAMPOLINE.len(),
Architecture::X86_64 => X86_64_TRAMPOLINE.len(),
Architecture::Riscv64(_) => RISCV64_TRAMPOLINE.len(),
Architecture::LoongArch64 => LOONGARCH64_TRAMPOLINE.len(),
arch => panic!("Unsupported architecture: {}", arch),
}
}
Expand Down
24 changes: 24 additions & 0 deletions lib/compiler/src/engine/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,30 @@ fn apply_relocation(
| read_unaligned(reloc_address as *mut u64);
write_unaligned(reloc_address as *mut u64, reloc_delta);
},
RelocationKind::LArchAbsHi20 => unsafe {
let (reloc_address, reloc_abs) = r.for_address(body, target_func_address as u64);
let reloc_abs = ((((reloc_abs >> 12) & 0xfffff) as u32) << 5)
| read_unaligned(reloc_address as *mut u32);
write_unaligned(reloc_address as *mut u32, reloc_abs);
},
RelocationKind::LArchAbsLo12 => unsafe {
let (reloc_address, reloc_abs) = r.for_address(body, target_func_address as u64);
let reloc_abs =
(((reloc_abs & 0xfff) as u32) << 10) | read_unaligned(reloc_address as *mut u32);
write_unaligned(reloc_address as *mut u32, reloc_abs);
},
RelocationKind::LArchAbs64Hi12 => unsafe {
let (reloc_address, reloc_abs) = r.for_address(body, target_func_address as u64);
let reloc_abs = ((((reloc_abs >> 52) & 0xfff) as u32) << 10)
| read_unaligned(reloc_address as *mut u32);
write_unaligned(reloc_address as *mut u32, reloc_abs);
},
RelocationKind::LArchAbs64Lo20 => unsafe {
let (reloc_address, reloc_abs) = r.for_address(body, target_func_address as u64);
let reloc_abs = ((((reloc_abs >> 32) & 0xfffff) as u32) << 5)
| read_unaligned(reloc_address as *mut u32);
write_unaligned(reloc_address as *mut u32, reloc_abs);
},
kind => panic!(
"Relocation kind unsupported in the current architecture {}",
kind
Expand Down
1 change: 1 addition & 0 deletions lib/object/src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ pub fn get_object_for_target(triple: &Triple) -> Result<Object, ObjectError> {
Architecture::X86_64 => object::Architecture::X86_64,
Architecture::Aarch64(_) => object::Architecture::Aarch64,
Architecture::Riscv64(_) => object::Architecture::Riscv64,
Architecture::LoongArch64 => object::Architecture::LoongArch64,
architecture => {
return Err(ObjectError::UnsupportedArchitecture(format!(
"{}",
Expand Down
12 changes: 12 additions & 0 deletions lib/types/src/compilation/relocation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ pub enum RelocationKind {
RiscvPCRelLo12I,
/// RISC-V call target
RiscvCall,
/// LoongArch absolute high 20bit
LArchAbsHi20,
/// LoongArch absolute low 12bit
LArchAbsLo12,
/// LoongArch absolute high 12bit
LArchAbs64Hi12,
/// LoongArch absolute low 20bit
LArchAbs64Lo20,
/// Elf x86_64 32 bit signed PC relative offset to two GOT entries for GD symbol.
ElfX86_64TlsGd,
// /// Mach-O x86_64 32 bit signed PC relative offset to a `__thread_vars` entry.
Expand All @@ -90,6 +98,10 @@ impl fmt::Display for RelocationKind {
Self::ElfX86_64TlsGd => write!(f, "ElfX86_64TlsGd"),
Self::RiscvPCRelHi20 => write!(f, "RiscvPCRelHi20"),
Self::RiscvPCRelLo12I => write!(f, "RiscvPCRelLo12I"),
Self::LArchAbsHi20 => write!(f, "LArchAbsHi20"),
Self::LArchAbsLo12 => write!(f, "LArchAbsLo12"),
Self::LArchAbs64Hi12 => write!(f, "LArchAbs64Hi12"),
Self::LArchAbs64Lo20 => write!(f, "LArchAbs64Lo20"),
// Self::MachOX86_64Tlv => write!(f, "MachOX86_64Tlv"),
}
}
Expand Down
11 changes: 11 additions & 0 deletions lib/vm/src/trap/traphandlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,9 @@ cfg_if::cfg_if! {
} else if #[cfg(all(target_os = "freebsd", target_arch = "aarch64"))] {
pc = context.uc_mcontext.mc_gpregs.gp_elr as usize;
sp = context.uc_mcontext.mc_gpregs.gp_sp as usize;
} else if #[cfg(all(target_os = "linux", target_arch = "loongarch64"))] {
pc = context.uc_mcontext.__gregs[1] as usize;
sp = context.uc_mcontext.__gregs[3] as usize;
} else {
compile_error!("Unsupported platform");
}
Expand Down Expand Up @@ -461,6 +464,14 @@ cfg_if::cfg_if! {
context.uc_mcontext.mc_gpregs.gp_x[1] = x1 as libc::register_t;
context.uc_mcontext.mc_gpregs.gp_x[29] = x29 as libc::register_t;
context.uc_mcontext.mc_gpregs.gp_x[30] = lr as libc::register_t;
} else if #[cfg(all(target_os = "linux", target_arch = "loongarch64"))] {
let TrapHandlerRegs { pc, sp, a0, a1, fp, ra } = regs;
context.uc_mcontext.__pc = pc;
context.uc_mcontext.__gregs[1] = ra;
context.uc_mcontext.__gregs[3] = sp;
context.uc_mcontext.__gregs[4] = a0;
context.uc_mcontext.__gregs[5] = a1;
context.uc_mcontext.__gregs[22] = fp;
} else {
compile_error!("Unsupported platform");
}
Expand Down
Loading

0 comments on commit 1bb7399

Please sign in to comment.