about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-03-14 11:46:57 +0000
committerbors <bors@rust-lang.org>2021-03-14 11:46:57 +0000
commit84c08f82b46986fcd5cbd1a637582bd1325fa970 (patch)
tree6678d7e243f4636cb97dda900790c6cdc687d091
parentf293f70dd848ae2371b6fad2eb9f4081e920da88 (diff)
parent71418384d7d37b37eef250291ea8015667a81f17 (diff)
downloadrust-84c08f82b46986fcd5cbd1a637582bd1325fa970.tar.gz
rust-84c08f82b46986fcd5cbd1a637582bd1325fa970.zip
Auto merge of #83044 - kubo39:set-llvm-code-model, r=nikic
Add support for storing code model to LLVM module IR

This patch avoids undefined behavior by linking different object files.
Also this would it could be propagated properly to LTO.

See https://reviews.llvm.org/D52322 and https://reviews.llvm.org/D52323.

This patch is based on https://github.com/rust-lang/rust/pull/74002
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs8
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs1
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp8
-rw-r--r--src/test/codegen/codemodels.rs20
5 files changed, 38 insertions, 1 deletions
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index c224da7885b..4b7bcf05501 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -140,7 +140,7 @@ fn to_llvm_relocation_model(relocation_model: RelocModel) -> llvm::RelocModel {
     }
 }
 
-fn to_llvm_code_model(code_model: Option<CodeModel>) -> llvm::CodeModel {
+pub(crate) fn to_llvm_code_model(code_model: Option<CodeModel>) -> llvm::CodeModel {
     match code_model {
         Some(CodeModel::Tiny) => llvm::CodeModel::Tiny,
         Some(CodeModel::Small) => llvm::CodeModel::Small,
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 9f6a2ae3ca1..21473f3b114 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -1,4 +1,5 @@
 use crate::attributes;
+use crate::back::write::to_llvm_code_model;
 use crate::callee::get_fn;
 use crate::coverageinfo;
 use crate::debuginfo;
@@ -181,6 +182,13 @@ pub unsafe fn create_module(
         }
     }
 
+    // Linking object files with different code models is undefined behavior
+    // because the compiler would have to generate additional code (to span
+    // longer jumps) if a larger code model is used with a smaller one.
+    //
+    // See https://reviews.llvm.org/D52322 and https://reviews.llvm.org/D52323.
+    llvm::LLVMRustSetModuleCodeModel(llmod, to_llvm_code_model(sess.code_model()));
+
     // If skipping the PLT is enabled, we need to add some module metadata
     // to ensure intrinsic calls don't use it.
     if !sess.needs_plt() {
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index e6d60044c84..82cd1be3b3b 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -2326,6 +2326,7 @@ extern "C" {
     pub fn LLVMRustUnsetComdat(V: &Value);
     pub fn LLVMRustSetModulePICLevel(M: &Module);
     pub fn LLVMRustSetModulePIELevel(M: &Module);
+    pub fn LLVMRustSetModuleCodeModel(M: &Module, Model: CodeModel);
     pub fn LLVMRustModuleBufferCreate(M: &Module) -> &'static mut ModuleBuffer;
     pub fn LLVMRustModuleBufferPtr(p: &ModuleBuffer) -> *const u8;
     pub fn LLVMRustModuleBufferLen(p: &ModuleBuffer) -> usize;
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index e7c210b6c7a..51c80cf7dfa 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -1264,6 +1264,14 @@ extern "C" void LLVMRustSetModulePIELevel(LLVMModuleRef M) {
   unwrap(M)->setPIELevel(PIELevel::Level::Large);
 }
 
+extern "C" void LLVMRustSetModuleCodeModel(LLVMModuleRef M,
+                                           LLVMRustCodeModel Model) {
+  auto CM = fromRust(Model);
+  if (!CM.hasValue())
+    return;
+  unwrap(M)->setCodeModel(*CM);
+}
+
 // Here you'll find an implementation of ThinLTO as used by the Rust compiler
 // right now. This ThinLTO support is only enabled on "recent ish" versions of
 // LLVM, and otherwise it's just blanket rejected from other compilers.
diff --git a/src/test/codegen/codemodels.rs b/src/test/codegen/codemodels.rs
new file mode 100644
index 00000000000..2328f5feb4e
--- /dev/null
+++ b/src/test/codegen/codemodels.rs
@@ -0,0 +1,20 @@
+// only-x86_64
+
+// revisions: NOMODEL MODEL-SMALL MODEL-KERNEL MODEL-MEDIUM MODEL-LARGE
+//[NOMODEL] compile-flags:
+//[MODEL-SMALL] compile-flags: -C code-model=small
+//[MODEL-KERNEL] compile-flags: -C code-model=kernel
+//[MODEL-MEDIUM] compile-flags: -C code-model=medium
+//[MODEL-LARGE] compile-flags: -C code-model=large
+
+#![crate_type = "lib"]
+
+// MODEL-SMALL: !llvm.module.flags = !{{{.*}}}
+// MODEL-SMALL: !{{[0-9]+}} = !{i32 1, !"Code Model", i32 1}
+// MODEL-KERNEL: !llvm.module.flags = !{{{.*}}}
+// MODEL-KERNEL: !{{[0-9]+}} = !{i32 1, !"Code Model", i32 2}
+// MODEL-MEDIUM: !llvm.module.flags = !{{{.*}}}
+// MODEL-MEDIUM: !{{[0-9]+}} = !{i32 1, !"Code Model", i32 3}
+// MODEL-LARGE: !llvm.module.flags = !{{{.*}}}
+// MODEL-LARGE: !{{[0-9]+}} = !{i32 1, !"Code Model", i32 4}
+// NOMODEL-NOT: Code Model