about summary refs log tree commit diff
path: root/compiler/rustc_codegen_llvm/src
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2020-09-21 10:40:35 +0200
committerGitHub <noreply@github.com>2020-09-21 10:40:35 +0200
commit02d787bef8b6b12523253cf24f79df5c1428959c (patch)
tree051df296ae31184847dcef5af408899b3b849055 /compiler/rustc_codegen_llvm/src
parent9e2ebf31ddb83ed3dd22ae16a5120d1178a7d370 (diff)
parent0bc405e3521d84cfaef7d94f1ae40c6c16796c8b (diff)
downloadrust-02d787bef8b6b12523253cf24f79df5c1428959c.tar.gz
rust-02d787bef8b6b12523253cf24f79df5c1428959c.zip
Rollup merge of #76872 - khyperia:remove_declare_methods, r=eddyb
Remove DeclareMethods

Most of the `DeclareMethods` API was only used internally by rustc_codegen_llvm. As such, it makes no sense to require other backends to implement them.

(`get_declared_value` and `declare_cfn` were used, in one place, specific to the `main` symbol, which I've replaced with a more specialized function to allow more flexibility in implementation - the intent is that `declare_c_main` can go away once we do something more clever, e.g. @eddyb has ideas around having a MIR shim or somesuch we can explore in a follow-up PR)
Diffstat (limited to 'compiler/rustc_codegen_llvm/src')
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs11
-rw-r--r--compiler/rustc_codegen_llvm/src/declare.rs43
2 files changed, 46 insertions, 8 deletions
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 1c51a9df5d8..1696f35563d 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -433,6 +433,17 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
             llvm::LLVMSetSection(g, section.as_ptr());
         }
     }
+
+    fn declare_c_main(&self, fn_type: Self::Type) -> Option<Self::Function> {
+        if self.get_declared_value("main").is_none() {
+            Some(self.declare_cfn("main", fn_type))
+        } else {
+            // If the symbol already exists, it is an error: for example, the user wrote
+            // #[no_mangle] extern "C" fn main(..) {..}
+            // instead of #[start]
+            None
+        }
+    }
 }
 
 impl CodegenCx<'b, 'tcx> {
diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs
index ec42bd4a039..a3d6882940a 100644
--- a/compiler/rustc_codegen_llvm/src/declare.rs
+++ b/compiler/rustc_codegen_llvm/src/declare.rs
@@ -51,17 +51,32 @@ fn declare_raw_fn(
     llfn
 }
 
-impl DeclareMethods<'tcx> for CodegenCx<'ll, 'tcx> {
-    fn declare_global(&self, name: &str, ty: &'ll Type) -> &'ll Value {
+impl CodegenCx<'ll, 'tcx> {
+    /// Declare a global value.
+    ///
+    /// If there’s a value with the same name already declared, the function will
+    /// return its Value instead.
+    pub fn declare_global(&self, name: &str, ty: &'ll Type) -> &'ll Value {
         debug!("declare_global(name={:?})", name);
         unsafe { llvm::LLVMRustGetOrInsertGlobal(self.llmod, name.as_ptr().cast(), name.len(), ty) }
     }
 
-    fn declare_cfn(&self, name: &str, fn_type: &'ll Type) -> &'ll Value {
+    /// Declare a C ABI function.
+    ///
+    /// Only use this for foreign function ABIs and glue. For Rust functions use
+    /// `declare_fn` instead.
+    ///
+    /// If there’s a value with the same name already declared, the function will
+    /// update the declaration and return existing Value instead.
+    pub fn declare_cfn(&self, name: &str, fn_type: &'ll Type) -> &'ll Value {
         declare_raw_fn(self, name, llvm::CCallConv, fn_type)
     }
 
-    fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> &'ll Value {
+    /// Declare a Rust function.
+    ///
+    /// If there’s a value with the same name already declared, the function will
+    /// update the declaration and return existing Value instead.
+    pub fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> &'ll Value {
         debug!("declare_rust_fn(name={:?}, fn_abi={:?})", name, fn_abi);
 
         let llfn = declare_raw_fn(self, name, fn_abi.llvm_cconv(), fn_abi.llvm_type(self));
@@ -69,7 +84,13 @@ impl DeclareMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         llfn
     }
 
-    fn define_global(&self, name: &str, ty: &'ll Type) -> Option<&'ll Value> {
+    /// Declare a global with an intention to define it.
+    ///
+    /// Use this function when you intend to define a global. This function will
+    /// return `None` if the name already has a definition associated with it. In that
+    /// case an error should be reported to the user, because it usually happens due
+    /// to user’s fault (e.g., misuse of `#[no_mangle]` or `#[export_name]` attributes).
+    pub fn define_global(&self, name: &str, ty: &'ll Type) -> Option<&'ll Value> {
         if self.get_defined_value(name).is_some() {
             None
         } else {
@@ -77,16 +98,22 @@ impl DeclareMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         }
     }
 
-    fn define_private_global(&self, ty: &'ll Type) -> &'ll Value {
+    /// Declare a private global
+    ///
+    /// Use this function when you intend to define a global without a name.
+    pub fn define_private_global(&self, ty: &'ll Type) -> &'ll Value {
         unsafe { llvm::LLVMRustInsertPrivateGlobal(self.llmod, ty) }
     }
 
-    fn get_declared_value(&self, name: &str) -> Option<&'ll Value> {
+    /// Gets declared value by name.
+    pub fn get_declared_value(&self, name: &str) -> Option<&'ll Value> {
         debug!("get_declared_value(name={:?})", name);
         unsafe { llvm::LLVMRustGetNamedValue(self.llmod, name.as_ptr().cast(), name.len()) }
     }
 
-    fn get_defined_value(&self, name: &str) -> Option<&'ll Value> {
+    /// Gets defined or externally defined (AvailableExternally linkage) value by
+    /// name.
+    pub fn get_defined_value(&self, name: &str) -> Option<&'ll Value> {
         self.get_declared_value(name).and_then(|val| {
             let declaration = unsafe { llvm::LLVMIsDeclaration(val) != 0 };
             if !declaration { Some(val) } else { None }