diff --git a/lib/compiler-llvm/src/config.rs b/lib/compiler-llvm/src/config.rs index 417488c3f3b..99664493fc7 100644 --- a/lib/compiler-llvm/src/config.rs +++ b/lib/compiler-llvm/src/config.rs @@ -221,7 +221,7 @@ impl LLVM { self.opt_level, self.reloc_mode(), match triple.architecture { - Architecture::Riscv64(_) => CodeModel::Medium, + Architecture::LoongArch64 | Architecture::Riscv64(_) => CodeModel::Medium, _ => self.code_model(), }, ) diff --git a/lib/compiler-llvm/src/object_file.rs b/lib/compiler-llvm/src/object_file.rs index dbe921e4a85..3e9fbbb8fde 100644 --- a/lib/compiler-llvm/src/object_file.rs +++ b/lib/compiler-llvm/src/object_file.rs @@ -254,6 +254,34 @@ where object::RelocationKind::Elf(object::elf::R_LARCH_ABS64_LO20), 0, ) => RelocationKind::LArchAbs64Lo20, + ( + object::Architecture::LoongArch64, + // FIXME: Replace with R_LARCH_CALL36 while object is updated + // to 0.32.2. + // https://github.com/gimli-rs/object/commit/16b6d902f6c9b39ec7aaea141460f8981e57dd79 + object::RelocationKind::Elf(110), + 0, + ) => RelocationKind::LArchCall36, + ( + object::Architecture::LoongArch64, + object::RelocationKind::Elf(object::elf::R_LARCH_PCALA_HI20), + 0, + ) => RelocationKind::LArchPCAlaHi20, + ( + object::Architecture::LoongArch64, + object::RelocationKind::Elf(object::elf::R_LARCH_PCALA_LO12), + 0, + ) => RelocationKind::LArchPCAlaLo12, + ( + object::Architecture::LoongArch64, + object::RelocationKind::Elf(object::elf::R_LARCH_PCALA64_HI12), + 0, + ) => RelocationKind::LArchPCAla64Hi12, + ( + object::Architecture::LoongArch64, + object::RelocationKind::Elf(object::elf::R_LARCH_PCALA64_LO20), + 0, + ) => RelocationKind::LArchPCAla64Lo20, ( object::Architecture::Aarch64, object::RelocationKind::Elf(object::elf::R_AARCH64_ADR_PREL_LO21), diff --git a/lib/compiler/src/artifact_builders/trampoline.rs b/lib/compiler/src/artifact_builders/trampoline.rs index 3206155e15f..f4b622b9d0d 100644 --- a/lib/compiler/src/artifact_builders/trampoline.rs +++ b/lib/compiler/src/artifact_builders/trampoline.rs @@ -45,7 +45,7 @@ const RISCV64_TRAMPOLINE: [u8; 24] = [ // 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, + 0x0c, 0x00, 0x00, 0x18, 0x8c, 0x41, 0xc0, 0x28, 0x80, 0x01, 0x00, 0x4c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]; diff --git a/lib/compiler/src/engine/link.rs b/lib/compiler/src/engine/link.rs index 5ba13439e5d..dd167aecf6d 100644 --- a/lib/compiler/src/engine/link.rs +++ b/lib/compiler/src/engine/link.rs @@ -127,30 +127,39 @@ fn apply_relocation( | read_unaligned(reloc_address as *mut u64); write_unaligned(reloc_address as *mut u64, reloc_delta); }, - RelocationKind::LArchAbsHi20 => unsafe { + RelocationKind::LArchAbsHi20 | RelocationKind::LArchPCAlaHi20 => 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 { + RelocationKind::LArchAbsLo12 | RelocationKind::LArchPCAlaLo12 => 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 { + RelocationKind::LArchAbs64Hi12 | RelocationKind::LArchPCAla64Hi12 => 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 { + RelocationKind::LArchAbs64Lo20 | RelocationKind::LArchPCAla64Lo20 => 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); }, + RelocationKind::LArchCall36 => unsafe { + let (reloc_address, reloc_delta) = r.for_address(body, target_func_address as u64); + let reloc_delta1 = ((((reloc_delta >> 18) & 0xfffff) as u32) << 5) + | read_unaligned(reloc_address as *mut u32); + write_unaligned(reloc_address as *mut u32, reloc_delta1); + let reloc_delta2 = ((((reloc_delta >> 2) & 0xffff) as u32) << 10) + | read_unaligned((reloc_address + 4) as *mut u32); + write_unaligned((reloc_address + 4) as *mut u32, reloc_delta2); + }, RelocationKind::Aarch64AdrPrelPgHi21 => unsafe { let (reloc_address, delta) = r.for_address(body, target_func_address as u64); diff --git a/lib/compiler/src/types/relocation.rs b/lib/compiler/src/types/relocation.rs index 3ab78d959ca..36590a75e4f 100644 --- a/lib/compiler/src/types/relocation.rs +++ b/lib/compiler/src/types/relocation.rs @@ -85,6 +85,16 @@ pub enum RelocationKind { LArchAbs64Hi12, /// LoongArch absolute low 20bit LArchAbs64Lo20, + /// LoongArch PC-relative call 38bit + LArchCall36, + /// LoongArch PC-relative high 20bit + LArchPCAlaHi20, + /// LoongArch PC-relative low 12bit + LArchPCAlaLo12, + /// LoongArch PC64-relative high 12bit + LArchPCAla64Hi12, + /// LoongArch PC64-relative low 20bit + LArchPCAla64Lo20, /// 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. @@ -115,6 +125,11 @@ impl fmt::Display for RelocationKind { Self::LArchAbsLo12 => write!(f, "LArchAbsLo12"), Self::LArchAbs64Hi12 => write!(f, "LArchAbs64Hi12"), Self::LArchAbs64Lo20 => write!(f, "LArchAbs64Lo20"), + Self::LArchCall36 => write!(f, "LArchCall36"), + Self::LArchPCAlaHi20 => write!(f, "LArchPCAlaHi20"), + Self::LArchPCAlaLo12 => write!(f, "LArchPCAlaLo12"), + Self::LArchPCAla64Hi12 => write!(f, "LArchPCAla64Hi12"), + Self::LArchPCAla64Lo20 => write!(f, "LArchPCAla64Lo20"), Self::Aarch64AdrPrelLo21 => write!(f, "Aarch64AdrPrelLo21"), Self::Aarch64AdrPrelPgHi21 => write!(f, "Aarch64AdrPrelPgHi21"), Self::Aarch64AddAbsLo12Nc => write!(f, "Aarch64AddAbsLo12Nc"), @@ -172,7 +187,12 @@ pub trait RelocationLike { | RelocationKind::Arm64Movw3 | RelocationKind::RiscvPCRelLo12I | RelocationKind::Aarch64Ldst128AbsLo12Nc - | RelocationKind::Aarch64Ldst64AbsLo12Nc => { + | RelocationKind::Aarch64Ldst64AbsLo12Nc + | RelocationKind::LArchAbsHi20 + | RelocationKind::LArchAbsLo12 + | RelocationKind::LArchAbs64Lo20 + | RelocationKind::LArchAbs64Hi12 + | RelocationKind::LArchPCAlaLo12 => { let reloc_address = start + self.offset() as usize; let reloc_addend = self.addend() as isize; let reloc_abs = target_func_address @@ -239,6 +259,45 @@ pub trait RelocationLike { let pc_page = reloc_address & !(0xFFF); (reloc_address, target_page.wrapping_sub(pc_page) as u64) } + RelocationKind::LArchCall36 => { + let reloc_address = start + self.offset() as usize; + let reloc_addend = self.addend() as isize; + let reloc_delta = target_func_address + .wrapping_sub(reloc_address as u64) + .wrapping_add(reloc_addend as u64); + ( + reloc_address, + reloc_delta.wrapping_add((reloc_delta & 0x20000) << 1), + ) + } + RelocationKind::LArchPCAlaHi20 => { + 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) + .wrapping_add(0x800) + & !(0xFFF)) as usize; + let pc_page = reloc_address & !(0xFFF); + (reloc_address, target_page.wrapping_sub(pc_page) as u64) + } + RelocationKind::LArchPCAla64Hi12 | RelocationKind::LArchPCAla64Lo20 => { + let reloc_address = start + self.offset() as usize; + let reloc_addend = self.addend() as isize; + let reloc_offset = match self.kind() { + RelocationKind::LArchPCAla64Lo20 => 8, + RelocationKind::LArchPCAla64Hi12 => 12, + _ => 0, + }; + let target_func_address = target_func_address.wrapping_add(reloc_addend as u64); + let target_page = (target_func_address & !(0xFFF)) as usize; + let pc_page = (reloc_address - reloc_offset) & !(0xFFF); + let mut reloc_delta = target_page.wrapping_sub(pc_page) as u64; + reloc_delta = reloc_delta + .wrapping_add((target_func_address & 0x800) << 1) + .wrapping_sub((target_func_address & 0x800) << 21); + reloc_delta = reloc_delta.wrapping_add((reloc_delta & 0x80000000) << 1); + (reloc_address, reloc_delta) + } _ => panic!("Relocation kind unsupported"), } }