Skip to content

Commit

Permalink
RISC-V support in universal engine
Browse files Browse the repository at this point in the history
  • Loading branch information
tnayuki authored and ptitSeb committed Oct 20, 2022
1 parent 2656c70 commit 0ccc9ce
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 4 deletions.
25 changes: 24 additions & 1 deletion lib/compiler-llvm/src/object_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,14 +197,24 @@ where
object::RelocationKind::Elf(object::elf::R_RISCV_CALL_PLT),
0,
) => RelocationKind::RiscvCall,
(
object::Architecture::Riscv64,
object::RelocationKind::Elf(object::elf::R_RISCV_PCREL_HI20),
0,
) => RelocationKind::RiscvPCRelHi20,
(
object::Architecture::Riscv64,
object::RelocationKind::Elf(object::elf::R_RISCV_PCREL_LO12_I),
0,
) => RelocationKind::RiscvPCRelLo12I,
_ => {
return Err(CompileError::Codegen(format!(
"unknown relocation {:?}",
reloc
)));
}
};
let addend = reloc.addend();
let mut addend = reloc.addend();
let target = match reloc.target() {
object::read::RelocationTarget::Symbol(index) => {
let symbol = elf.symbol_by_index(index).map_err(map_object_err)?;
Expand Down Expand Up @@ -235,6 +245,19 @@ where
symbol_name_to_relocation_target(symbol_name)?
{
reloc_target
} else if let object::SymbolSection::Section(section_index) = symbol.section() {
// TODO: Encode symbol address into addend, I think this is a bit hacky.
addend = addend.wrapping_add(symbol.address() as i64);

if section_index == root_section_index {
root_section_reloc_target
} else {
if visited.insert(section_index) {
worklist.push(section_index);
}

elf_section_to_target(section_index)
}
} else {
return Err(CompileError::Codegen(format!(
"relocation targets unknown symbol {:?}",
Expand Down
21 changes: 21 additions & 0 deletions lib/compiler/src/artifact_builders/trampoline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,17 @@ const X86_64_TRAMPOLINE: [u8; 16] = [
0xff, 0x25, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];

// can it be shorter than this?
// 4 padding bytes are used to preserve alignment.
// AUIPC t1,0 17 03 00 00
// LD t1, 16(t1) 03 33 03 01
// JR t1 67 00 03 00 [00 00 00 00]
// JMPADDR 00 00 00 00 00 00 00 00
const RISCV64_TRAMPOLINE: [u8; 24] = [
0x17, 0x03, 0x00, 0x00, 0x03, 0x33, 0x03, 0x01, 0x67, 0x00, 0x03, 0x00, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,
];

fn make_trampoline(
target: &Target,
libcall: LibCall,
Expand All @@ -50,6 +61,15 @@ fn make_trampoline(
addend: 0,
});
}
Architecture::Riscv64(_) => {
code.extend(&RISCV64_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 @@ -59,6 +79,7 @@ pub fn libcall_trampoline_len(target: &Target) -> usize {
match target.triple().architecture {
Architecture::Aarch64(_) => AARCH64_TRAMPOLINE.len(),
Architecture::X86_64 => X86_64_TRAMPOLINE.len(),
Architecture::Riscv64(_) => RISCV64_TRAMPOLINE.len(),
arch => panic!("Unsupported architecture: {}", arch),
}
}
Expand Down
32 changes: 32 additions & 0 deletions lib/compiler/src/engine/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
use crate::get_libcall_trampoline;
use crate::FunctionExtent;
use std::collections::HashMap;
use std::ptr::{read_unaligned, write_unaligned};
use wasmer_types::entity::PrimaryMap;
use wasmer_types::{LocalFunctionIndex, ModuleInfo};
Expand All @@ -16,6 +17,7 @@ fn apply_relocation(
allocated_sections: &PrimaryMap<SectionIndex, SectionBodyPtr>,
libcall_trampolines: SectionIndex,
libcall_trampoline_len: usize,
riscv_pcrel_hi20s: &mut HashMap<usize, u32>,
) {
let target_func_address: usize = match r.reloc_target {
RelocationTarget::LocalFunc(index) => *allocated_functions[index].ptr as usize,
Expand Down Expand Up @@ -93,6 +95,32 @@ fn apply_relocation(
| read_unaligned(reloc_address as *mut u32);
write_unaligned(reloc_address as *mut u32, reloc_delta);
},
RelocationKind::RiscvPCRelHi20 => unsafe {
let (reloc_address, reloc_delta) = r.for_address(body, target_func_address as u64);

// save for later reference with RiscvPCRelLo12I
riscv_pcrel_hi20s.insert(reloc_address, reloc_delta as u32);

let reloc_delta = ((reloc_delta.wrapping_add(0x800) & 0xfffff000) as u32)
| read_unaligned(reloc_address as *mut u32);
write_unaligned(reloc_address as *mut u32, reloc_delta);
},
RelocationKind::RiscvPCRelLo12I => unsafe {
let (reloc_address, reloc_abs) = r.for_address(body, target_func_address as u64);
let reloc_delta = ((riscv_pcrel_hi20s.get(&(reloc_abs as usize)).expect(
"R_RISCV_PCREL_LO12_I relocation target must be a symbol with R_RISCV_PCREL_HI20",
) & 0xfff)
<< 20)
| read_unaligned(reloc_address as *mut u32);
write_unaligned(reloc_address as *mut u32, reloc_delta);
},
RelocationKind::RiscvCall => unsafe {
let (reloc_address, reloc_delta) = r.for_address(body, target_func_address as u64);
let reloc_delta = ((reloc_delta & 0xfff) << 52)
| (reloc_delta.wrapping_add(0x800) & 0xfffff000)
| read_unaligned(reloc_address as *mut u64);
write_unaligned(reloc_address as *mut u64, reloc_delta);
},
kind => panic!(
"Relocation kind unsupported in the current architecture {}",
kind
Expand All @@ -111,6 +139,8 @@ pub fn link_module(
libcall_trampolines: SectionIndex,
trampoline_len: usize,
) {
let mut riscv_pcrel_hi20s: HashMap<usize, u32> = HashMap::new();

for (i, section_relocs) in section_relocations.iter() {
let body = *allocated_sections[i] as usize;
for r in section_relocs {
Expand All @@ -121,6 +151,7 @@ pub fn link_module(
allocated_sections,
libcall_trampolines,
trampoline_len,
&mut riscv_pcrel_hi20s,
);
}
}
Expand All @@ -134,6 +165,7 @@ pub fn link_module(
allocated_sections,
libcall_trampolines,
trampoline_len,
&mut riscv_pcrel_hi20s,
);
}
}
Expand Down
13 changes: 11 additions & 2 deletions lib/types/src/compilation/relocation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ pub enum RelocationKind {
Arm64Movw2,
/// Arm64 movk/z part 3
Arm64Movw3,
/// RISC-V PC-relative high 20bit
RiscvPCRelHi20,
/// RISC-V PC-relative low 12bit, I-type
RiscvPCRelLo12I,
/// RISC-V call target
RiscvCall,
/// Elf x86_64 32 bit signed PC relative offset to two GOT entries for GD symbol.
Expand All @@ -76,6 +80,8 @@ impl fmt::Display for RelocationKind {
Self::Arm64Movw2 => write!(f, "Arm64MovwG2"),
Self::Arm64Movw3 => write!(f, "Arm64MovwG3"),
Self::ElfX86_64TlsGd => write!(f, "ElfX86_64TlsGd"),
Self::RiscvPCRelHi20 => write!(f, "RiscvPCRelHi20"),
Self::RiscvPCRelLo12I => write!(f, "RiscvPCRelLo12I"),
// Self::MachOX86_64Tlv => write!(f, "MachOX86_64Tlv"),
}
}
Expand Down Expand Up @@ -119,7 +125,8 @@ impl Relocation {
| RelocationKind::Arm64Movw0
| RelocationKind::Arm64Movw1
| RelocationKind::Arm64Movw2
| RelocationKind::Arm64Movw3 => {
| RelocationKind::Arm64Movw3
| RelocationKind::RiscvPCRelLo12I => {
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 @@ -153,7 +160,9 @@ impl Relocation {
.wrapping_add(reloc_addend as u32);
(reloc_address, reloc_delta_u32 as u64)
}
RelocationKind::Arm64Call | RelocationKind::RiscvCall => {
RelocationKind::Arm64Call
| RelocationKind::RiscvCall
| RelocationKind::RiscvPCRelHi20 => {
let reloc_address = start + self.offset as usize;
let reloc_addend = self.addend as isize;
let reloc_delta_u32 = target_func_address
Expand Down
2 changes: 1 addition & 1 deletion lib/vm/src/trap/traphandlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1053,4 +1053,4 @@ pub fn lazy_per_thread_init() -> Result<(), Trap> {
}
}
}
}
}

0 comments on commit 0ccc9ce

Please sign in to comment.