]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #41560 - alevy:rwpi-ropi, r=eddyb
authorbors <bors@rust-lang.org>
Mon, 1 May 2017 17:23:09 +0000 (17:23 +0000)
committerbors <bors@rust-lang.org>
Mon, 1 May 2017 17:23:09 +0000 (17:23 +0000)
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)?

src/librustc_llvm/ffi.rs
src/librustc_trans/back/write.rs
src/rustllvm/PassWrapper.cpp

index 402166cc13fd933853955fa504921cbc238a62ae..5cb5a62c93b35ad6075c289283931ccf8d19b7ec 100644 (file)
@@ -284,10 +284,13 @@ pub enum CodeGenOptLevel {
 #[derive(Copy, Clone, PartialEq)]
 #[repr(C)]
 pub enum RelocMode {
-    Default = 0,
-    Static = 1,
-    PIC = 2,
-    DynamicNoPic = 3,
+    Default,
+    Static,
+    PIC,
+    DynamicNoPic,
+    ROPI,
+    RWPI,
+    ROPI_RWPI,
 }
 
 /// LLVMRustCodeModel
index ccb3f7ac882aa8b209a2492fc551df8a6d5ee0b8..3492403a1bf8e545e192c70ab7e526e1108f762d 100644 (file)
 use std::thread;
 use libc::{c_uint, c_void};
 
-pub const RELOC_MODEL_ARGS : [(&'static str, llvm::RelocMode); 4] = [
+pub const RELOC_MODEL_ARGS : [(&'static str, llvm::RelocMode); 7] = [
     ("pic", llvm::RelocMode::PIC),
     ("static", llvm::RelocMode::Static),
     ("default", llvm::RelocMode::Default),
     ("dynamic-no-pic", llvm::RelocMode::DynamicNoPic),
+    ("ropi", llvm::RelocMode::ROPI),
+    ("rwpi", llvm::RelocMode::RWPI),
+    ("ropi-rwpi", llvm::RelocMode::ROPI_RWPI),
 ];
 
 pub const CODE_GEN_MODEL_ARGS : [(&'static str, llvm::CodeModel); 5] = [
index b938f94cda2cb3596bf1cbbb8ef248b18a54cffe..fdbe4e5f7ad25209f2fa91148181dc30c9f267ee 100644 (file)
@@ -246,6 +246,47 @@ static CodeGenOpt::Level fromRust(LLVMRustCodeGenOptLevel Level) {
   }
 }
 
+enum class LLVMRustRelocMode {
+  Default,
+  Static,
+  PIC,
+  DynamicNoPic,
+  ROPI,
+  RWPI,
+  ROPIRWPI,
+};
+
+#if LLVM_VERSION_LE(3, 8)
+static Reloc::Model fromRust(LLVMRustRelocMode RustReloc) {
+#else
+static Optional<Reloc::Model> fromRust(LLVMRustRelocMode RustReloc) {
+#endif
+  switch (RustReloc) {
+  case LLVMRustRelocMode::Default:
+#if LLVM_VERSION_LE(3, 8)
+    return Reloc::Default;
+#else
+    return None;
+#endif
+  case LLVMRustRelocMode::Static:
+    return Reloc::Static;
+  case LLVMRustRelocMode::PIC:
+    return Reloc::PIC_;
+  case LLVMRustRelocMode::DynamicNoPic:
+    return Reloc::DynamicNoPIC;
+#if LLVM_VERSION_GE(4, 0)
+  case LLVMRustRelocMode::ROPI:
+    return Reloc::ROPI;
+  case LLVMRustRelocMode::RWPI:
+    return Reloc::RWPI;
+  case LLVMRustRelocMode::ROPIRWPI:
+    return Reloc::ROPI_RWPI;
+#endif
+  default:
+    llvm_unreachable("Bad RelocModel.");
+  }
+}
+
 #if LLVM_RUSTLLVM
 /// getLongestEntryLength - Return the length of the longest entry in the table.
 ///
@@ -297,35 +338,14 @@ extern "C" void LLVMRustPrintTargetFeatures(LLVMTargetMachineRef) {
 
 extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
     const char *TripleStr, const char *CPU, const char *Feature,
-    LLVMRustCodeModel RustCM, LLVMRelocMode Reloc,
+    LLVMRustCodeModel RustCM, LLVMRustRelocMode RustReloc,
     LLVMRustCodeGenOptLevel RustOptLevel, bool UseSoftFloat,
     bool PositionIndependentExecutable, bool FunctionSections,
     bool DataSections) {
 
-#if LLVM_VERSION_LE(3, 8)
-  Reloc::Model RM;
-#else
-  Optional<Reloc::Model> RM;
-#endif
   auto CM = fromRust(RustCM);
   auto OptLevel = fromRust(RustOptLevel);
-
-  switch (Reloc) {
-  case LLVMRelocStatic:
-    RM = Reloc::Static;
-    break;
-  case LLVMRelocPIC:
-    RM = Reloc::PIC_;
-    break;
-  case LLVMRelocDynamicNoPic:
-    RM = Reloc::DynamicNoPIC;
-    break;
-  default:
-#if LLVM_VERSION_LE(3, 8)
-    RM = Reloc::Default;
-#endif
-    break;
-  }
+  auto RM = fromRust(RustReloc);
 
   std::string Error;
   Triple Trip(Triple::normalize(TripleStr));