Skip to content

Commit 4cb396c

Browse files
committed
Auto merge of #41560 - alevy:rwpi-ropi, r=eddyb
Add RWPI/ROPI relocation model support This PR adds support for using LLVM 4's ROPI and RWPI relocation models for ARM. ROPI (Read-Only Position Independence) and RWPI (Read-Write Position Independence) are two new relocation models in LLVM for the ARM backend ([LLVM changset](https://reviews.llvm.org/rL278015)). The motivation is that these are the specific strategies we use in userspace [Tock](https://www.tockos.org) apps, so supporting this is an important step (perhaps the final step, but can't confirm yet) in enabling userspace Rust processes. ## Explanation ROPI makes all code and immutable accesses PC relative, but not assumed to be overriden at runtime (so for example, jumps are always relative). RWPI uses a base register (`r9`) that stores the addresses of the GOT in memory so the runtime (e.g. a kernel) only adjusts r9 tell running code where the GOT is. ## Complications adding support in Rust While this landed in LLVM master back in August, the header files in `llvm-c` have not been updated yet to reflect it. Rust replicates that header file's version of the `LLVMRelocMode` enum as the Rust enum `llvm::RelocMode` and uses an implicit cast in the ffi to translate from Rust's notion of the relocation model to the LLVM library's notion. My workaround for this currently is to replace the `LLVMRelocMode` argument to `LLVMTargetMachineRef` with an int and using the hardcoded int representation of the `RelocMode` enum. This is A Bad Idea(tm), but I think very nearly the right thing. Would a better alternative be to patch rust-llvm to support these enum variants (also a fairly trivial change)?
2 parents 526d399 + 0f00f27 commit 4cb396c

File tree

3 files changed

+54
-28
lines changed

3 files changed

+54
-28
lines changed

src/librustc_llvm/ffi.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -284,10 +284,13 @@ pub enum CodeGenOptLevel {
284284
#[derive(Copy, Clone, PartialEq)]
285285
#[repr(C)]
286286
pub enum RelocMode {
287-
Default = 0,
288-
Static = 1,
289-
PIC = 2,
290-
DynamicNoPic = 3,
287+
Default,
288+
Static,
289+
PIC,
290+
DynamicNoPic,
291+
ROPI,
292+
RWPI,
293+
ROPI_RWPI,
291294
}
292295

293296
/// LLVMRustCodeModel

src/librustc_trans/back/write.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,14 @@ use std::sync::mpsc::channel;
3737
use std::thread;
3838
use libc::{c_uint, c_void};
3939

40-
pub const RELOC_MODEL_ARGS : [(&'static str, llvm::RelocMode); 4] = [
40+
pub const RELOC_MODEL_ARGS : [(&'static str, llvm::RelocMode); 7] = [
4141
("pic", llvm::RelocMode::PIC),
4242
("static", llvm::RelocMode::Static),
4343
("default", llvm::RelocMode::Default),
4444
("dynamic-no-pic", llvm::RelocMode::DynamicNoPic),
45+
("ropi", llvm::RelocMode::ROPI),
46+
("rwpi", llvm::RelocMode::RWPI),
47+
("ropi-rwpi", llvm::RelocMode::ROPI_RWPI),
4548
];
4649

4750
pub const CODE_GEN_MODEL_ARGS : [(&'static str, llvm::CodeModel); 5] = [

src/rustllvm/PassWrapper.cpp

+43-23
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,47 @@ static CodeGenOpt::Level fromRust(LLVMRustCodeGenOptLevel Level) {
246246
}
247247
}
248248

249+
enum class LLVMRustRelocMode {
250+
Default,
251+
Static,
252+
PIC,
253+
DynamicNoPic,
254+
ROPI,
255+
RWPI,
256+
ROPIRWPI,
257+
};
258+
259+
#if LLVM_VERSION_LE(3, 8)
260+
static Reloc::Model fromRust(LLVMRustRelocMode RustReloc) {
261+
#else
262+
static Optional<Reloc::Model> fromRust(LLVMRustRelocMode RustReloc) {
263+
#endif
264+
switch (RustReloc) {
265+
case LLVMRustRelocMode::Default:
266+
#if LLVM_VERSION_LE(3, 8)
267+
return Reloc::Default;
268+
#else
269+
return None;
270+
#endif
271+
case LLVMRustRelocMode::Static:
272+
return Reloc::Static;
273+
case LLVMRustRelocMode::PIC:
274+
return Reloc::PIC_;
275+
case LLVMRustRelocMode::DynamicNoPic:
276+
return Reloc::DynamicNoPIC;
277+
#if LLVM_VERSION_GE(4, 0)
278+
case LLVMRustRelocMode::ROPI:
279+
return Reloc::ROPI;
280+
case LLVMRustRelocMode::RWPI:
281+
return Reloc::RWPI;
282+
case LLVMRustRelocMode::ROPIRWPI:
283+
return Reloc::ROPI_RWPI;
284+
#endif
285+
default:
286+
llvm_unreachable("Bad RelocModel.");
287+
}
288+
}
289+
249290
#if LLVM_RUSTLLVM
250291
/// getLongestEntryLength - Return the length of the longest entry in the table.
251292
///
@@ -297,35 +338,14 @@ extern "C" void LLVMRustPrintTargetFeatures(LLVMTargetMachineRef) {
297338

298339
extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
299340
const char *TripleStr, const char *CPU, const char *Feature,
300-
LLVMRustCodeModel RustCM, LLVMRelocMode Reloc,
341+
LLVMRustCodeModel RustCM, LLVMRustRelocMode RustReloc,
301342
LLVMRustCodeGenOptLevel RustOptLevel, bool UseSoftFloat,
302343
bool PositionIndependentExecutable, bool FunctionSections,
303344
bool DataSections) {
304345

305-
#if LLVM_VERSION_LE(3, 8)
306-
Reloc::Model RM;
307-
#else
308-
Optional<Reloc::Model> RM;
309-
#endif
310346
auto CM = fromRust(RustCM);
311347
auto OptLevel = fromRust(RustOptLevel);
312-
313-
switch (Reloc) {
314-
case LLVMRelocStatic:
315-
RM = Reloc::Static;
316-
break;
317-
case LLVMRelocPIC:
318-
RM = Reloc::PIC_;
319-
break;
320-
case LLVMRelocDynamicNoPic:
321-
RM = Reloc::DynamicNoPIC;
322-
break;
323-
default:
324-
#if LLVM_VERSION_LE(3, 8)
325-
RM = Reloc::Default;
326-
#endif
327-
break;
328-
}
348+
auto RM = fromRust(RustReloc);
329349

330350
std::string Error;
331351
Triple Trip(Triple::normalize(TripleStr));

0 commit comments

Comments
 (0)