Skip to content

Commit fe82b1f

Browse files
committed
RISC-V support in universal engine
1 parent 6bf4ea1 commit fe82b1f

File tree

5 files changed

+89
-3
lines changed

5 files changed

+89
-3
lines changed

Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ ifeq ($(ENABLE_LLVM), 1)
253253
compilers_engines += llvm-universal
254254
compilers_engines += llvm-dylib
255255
else ifeq ($(IS_RISCV64), 1)
256+
compilers_engines += llvm-universal
256257
compilers_engines += llvm-dylib
257258
endif
258259
endif

lib/compiler-llvm/src/object_file.rs

+24-1
Original file line numberDiff line numberDiff line change
@@ -198,14 +198,24 @@ where
198198
object::RelocationKind::Elf(object::elf::R_RISCV_CALL_PLT),
199199
0,
200200
) => RelocationKind::RiscvCall,
201+
(
202+
object::Architecture::Riscv64,
203+
object::RelocationKind::Elf(object::elf::R_RISCV_PCREL_HI20),
204+
0,
205+
) => RelocationKind::RiscvPCRelHi20,
206+
(
207+
object::Architecture::Riscv64,
208+
object::RelocationKind::Elf(object::elf::R_RISCV_PCREL_LO12_I),
209+
0,
210+
) => RelocationKind::RiscvPCRelLo12I,
201211
_ => {
202212
return Err(CompileError::Codegen(format!(
203213
"unknown relocation {:?}",
204214
reloc
205215
)));
206216
}
207217
};
208-
let addend = reloc.addend();
218+
let mut addend = reloc.addend();
209219
let target = match reloc.target() {
210220
object::read::RelocationTarget::Symbol(index) => {
211221
let symbol = elf.symbol_by_index(index).map_err(map_object_err)?;
@@ -236,6 +246,19 @@ where
236246
symbol_name_to_relocation_target(symbol_name)?
237247
{
238248
reloc_target
249+
} else if let object::SymbolSection::Section(section_index) = symbol.section() {
250+
// TODO: Encode symbol address into addend, I think this is a bit hacky.
251+
addend = addend.wrapping_add(symbol.address() as i64);
252+
253+
if section_index == root_section_index {
254+
root_section_reloc_target
255+
} else {
256+
if visited.insert(section_index) {
257+
worklist.push(section_index);
258+
}
259+
260+
elf_section_to_target(section_index)
261+
}
239262
} else {
240263
return Err(CompileError::Codegen(format!(
241264
"relocation targets unknown symbol {:?}",

lib/compiler/src/relocation.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ pub enum RelocationKind {
5858
Arm64Movw2,
5959
/// Arm64 movk/z part 3
6060
Arm64Movw3,
61+
/// RISC-V PC-relative high 20bit
62+
RiscvPCRelHi20,
63+
/// RISC-V PC-relative low 12bit, I-type
64+
RiscvPCRelLo12I,
6165
/// RISC-V call target
6266
RiscvCall,
6367
/// Elf x86_64 32 bit signed PC relative offset to two GOT entries for GD symbol.
@@ -85,6 +89,8 @@ impl fmt::Display for RelocationKind {
8589
Self::Arm64Movw2 => write!(f, "Arm64MovwG2"),
8690
Self::Arm64Movw3 => write!(f, "Arm64MovwG3"),
8791
Self::ElfX86_64TlsGd => write!(f, "ElfX86_64TlsGd"),
92+
Self::RiscvPCRelHi20 => write!(f, "RiscvPCRelHi20"),
93+
Self::RiscvPCRelLo12I => write!(f, "RiscvPCRelLo12I"),
8894
// Self::MachOX86_64Tlv => write!(f, "MachOX86_64Tlv"),
8995
}
9096
}
@@ -137,7 +143,8 @@ impl Relocation {
137143
| RelocationKind::Arm64Movw0
138144
| RelocationKind::Arm64Movw1
139145
| RelocationKind::Arm64Movw2
140-
| RelocationKind::Arm64Movw3 => {
146+
| RelocationKind::Arm64Movw3
147+
| RelocationKind::RiscvPCRelLo12I => {
141148
let reloc_address = start + self.offset as usize;
142149
let reloc_addend = self.addend as isize;
143150
let reloc_abs = target_func_address
@@ -171,7 +178,9 @@ impl Relocation {
171178
.wrapping_add(reloc_addend as u32);
172179
(reloc_address, reloc_delta_u32 as u64)
173180
}
174-
RelocationKind::Arm64Call | RelocationKind::RiscvCall => {
181+
RelocationKind::Arm64Call
182+
| RelocationKind::RiscvCall
183+
| RelocationKind::RiscvPCRelHi20 => {
175184
let reloc_address = start + self.offset as usize;
176185
let reloc_addend = self.addend as isize;
177186
let reloc_delta_u32 = target_func_address

lib/engine-universal/src/link.rs

+32
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Linking for Universal-compiled code.
22
33
use crate::trampoline::get_libcall_trampoline;
4+
use std::collections::HashMap;
45
use std::ptr::{read_unaligned, write_unaligned};
56
use wasmer_compiler::{
67
JumpTable, JumpTableOffsets, Relocation, RelocationKind, RelocationTarget, Relocations,
@@ -19,6 +20,7 @@ fn apply_relocation(
1920
allocated_sections: &PrimaryMap<SectionIndex, SectionBodyPtr>,
2021
libcall_trampolines: SectionIndex,
2122
libcall_trampoline_len: usize,
23+
riscv_pcrel_hi20s: &mut HashMap<usize, u32>,
2224
) {
2325
let target_func_address: usize = match r.reloc_target {
2426
RelocationTarget::LocalFunc(index) => *allocated_functions[index].ptr as usize,
@@ -107,6 +109,32 @@ fn apply_relocation(
107109
| read_unaligned(reloc_address as *mut u32);
108110
write_unaligned(reloc_address as *mut u32, reloc_delta);
109111
},
112+
RelocationKind::RiscvPCRelHi20 => unsafe {
113+
let (reloc_address, reloc_delta) = r.for_address(body, target_func_address as u64);
114+
115+
// save for later reference with RiscvPCRelLo12I
116+
riscv_pcrel_hi20s.insert(reloc_address, reloc_delta as u32);
117+
118+
let reloc_delta = ((reloc_delta.wrapping_add(0x800) & 0xfffff000) as u32)
119+
| read_unaligned(reloc_address as *mut u32);
120+
write_unaligned(reloc_address as *mut u32, reloc_delta);
121+
},
122+
RelocationKind::RiscvPCRelLo12I => unsafe {
123+
let (reloc_address, reloc_abs) = r.for_address(body, target_func_address as u64);
124+
let reloc_delta = ((riscv_pcrel_hi20s.get(&(reloc_abs as usize)).expect(
125+
"R_RISCV_PCREL_LO12_I relocation target must be a symbol with R_RISCV_PCREL_HI20",
126+
) & 0xfff)
127+
<< 20)
128+
| read_unaligned(reloc_address as *mut u32);
129+
write_unaligned(reloc_address as *mut u32, reloc_delta);
130+
},
131+
RelocationKind::RiscvCall => unsafe {
132+
let (reloc_address, reloc_delta) = r.for_address(body, target_func_address as u64);
133+
let reloc_delta = ((reloc_delta & 0xfff) << 52)
134+
| (reloc_delta.wrapping_add(0x800) & 0xfffff000)
135+
| read_unaligned(reloc_address as *mut u64);
136+
write_unaligned(reloc_address as *mut u64, reloc_delta);
137+
},
110138
kind => panic!(
111139
"Relocation kind unsupported in the current architecture {}",
112140
kind
@@ -126,6 +154,8 @@ pub fn link_module(
126154
libcall_trampolines: SectionIndex,
127155
trampoline_len: usize,
128156
) {
157+
let mut riscv_pcrel_hi20s: HashMap<usize, u32> = HashMap::new();
158+
129159
for (i, section_relocs) in section_relocations.iter() {
130160
let body = *allocated_sections[i] as usize;
131161
for r in section_relocs {
@@ -137,6 +167,7 @@ pub fn link_module(
137167
allocated_sections,
138168
libcall_trampolines,
139169
trampoline_len,
170+
&mut riscv_pcrel_hi20s,
140171
);
141172
}
142173
}
@@ -151,6 +182,7 @@ pub fn link_module(
151182
allocated_sections,
152183
libcall_trampolines,
153184
trampoline_len,
185+
&mut riscv_pcrel_hi20s,
154186
);
155187
}
156188
}

lib/engine-universal/src/trampoline.rs

+21
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,17 @@ const X86_64_TRAMPOLINE: [u8; 16] = [
2626
0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2727
];
2828

29+
// can it be shorter than this?
30+
// 4 padding bytes are used to preserve alignment.
31+
// AUIPC t1,0 17 03 00 00
32+
// LD t1, 16(t1) 03 33 03 01
33+
// JR t1 67 00 03 00 [00 00 00 00]
34+
// JMPADDR 00 00 00 00 00 00 00 00
35+
const RISCV64_TRAMPOLINE: [u8; 24] = [
36+
0x17, 0x03, 0x00, 0x00, 0x03, 0x33, 0x03, 0x01, 0x67, 0x00, 0x03, 0x00, 0, 0, 0, 0, 0, 0, 0, 0,
37+
0, 0, 0, 0,
38+
];
39+
2940
fn make_trampoline(
3041
target: &Target,
3142
libcall: LibCall,
@@ -51,6 +62,15 @@ fn make_trampoline(
5162
addend: 0,
5263
});
5364
}
65+
Architecture::Riscv64(_) => {
66+
code.extend(&RISCV64_TRAMPOLINE);
67+
relocations.push(Relocation {
68+
kind: RelocationKind::Abs8,
69+
reloc_target: RelocationTarget::LibCall(libcall),
70+
offset: code.len() as u32 - 8,
71+
addend: 0,
72+
});
73+
}
5474
arch => panic!("Unsupported architecture: {}", arch),
5575
};
5676
}
@@ -60,6 +80,7 @@ pub fn libcall_trampoline_len(target: &Target) -> usize {
6080
match target.triple().architecture {
6181
Architecture::Aarch64(_) => AARCH64_TRAMPOLINE.len(),
6282
Architecture::X86_64 => X86_64_TRAMPOLINE.len(),
83+
Architecture::Riscv64(_) => RISCV64_TRAMPOLINE.len(),
6384
arch => panic!("Unsupported architecture: {}", arch),
6485
}
6586
}

0 commit comments

Comments
 (0)