Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove DeclareMethods #76872

Merged
merged 1 commit into from
Sep 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions compiler/rustc_codegen_llvm/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down
43 changes: 35 additions & 8 deletions compiler/rustc_codegen_llvm/src/declare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,42 +51,69 @@ 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));
fn_abi.apply_attrs_llfn(self, llfn);
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 {
Some(self.declare_global(name, ty))
}
}

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 }
Expand Down
22 changes: 12 additions & 10 deletions compiler/rustc_codegen_ssa/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -407,16 +407,18 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
// listing.
let main_ret_ty = cx.tcx().erase_regions(&main_ret_ty.no_bound_vars().unwrap());

if cx.get_declared_value("main").is_some() {
// FIXME: We should be smart and show a better diagnostic here.
cx.sess()
.struct_span_err(sp, "entry symbol `main` declared multiple times")
.help("did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead")
.emit();
cx.sess().abort_if_errors();
bug!();
}
let llfn = cx.declare_cfn("main", llfty);
let llfn = match cx.declare_c_main(llfty) {
Some(llfn) => llfn,
None => {
// FIXME: We should be smart and show a better diagnostic here.
cx.sess()
.struct_span_err(sp, "entry symbol `main` declared multiple times")
.help("did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead")
.emit();
cx.sess().abort_if_errors();
bug!();
}
};

// `main` should respect same config for frame pointer elimination as rest of code
cx.set_frame_pointer_elimination(llfn);
Expand Down
46 changes: 1 addition & 45 deletions compiler/rustc_codegen_ssa/src/traits/declare.rs
Original file line number Diff line number Diff line change
@@ -1,51 +1,7 @@
use super::BackendTypes;
use rustc_hir::def_id::DefId;
use rustc_middle::mir::mono::{Linkage, Visibility};
use rustc_middle::ty::{Instance, Ty};
use rustc_target::abi::call::FnAbi;

pub trait DeclareMethods<'tcx>: BackendTypes {
/// Declare a global value.
///
/// If there’s a value with the same name already declared, the function will
/// return its Value instead.
fn declare_global(&self, name: &str, ty: Self::Type) -> Self::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.
fn declare_cfn(&self, name: &str, fn_type: Self::Type) -> Self::Function;

/// 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.
fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Self::Function;

/// 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).
fn define_global(&self, name: &str, ty: Self::Type) -> Option<Self::Value>;

/// Declare a private global
///
/// Use this function when you intend to define a global without a name.
fn define_private_global(&self, ty: Self::Type) -> Self::Value;

/// Gets declared value by name.
fn get_declared_value(&self, name: &str) -> Option<Self::Value>;

/// Gets defined or externally defined (AvailableExternally linkage) value by
/// name.
fn get_defined_value(&self, name: &str) -> Option<Self::Value>;
}
use rustc_middle::ty::Instance;

pub trait PreDefineMethods<'tcx>: BackendTypes {
fn predefine_static(
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_codegen_ssa/src/traits/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@ pub trait MiscMethods<'tcx>: BackendTypes {
fn set_frame_pointer_elimination(&self, llfn: Self::Function);
fn apply_target_cpu_attr(&self, llfn: Self::Function);
fn create_used_variable(&self);
/// Declares the extern "C" main function for the entry point. Returns None if the symbol already exists.
fn declare_c_main(&self, fn_type: Self::Type) -> Option<Self::Function>;
}
4 changes: 1 addition & 3 deletions compiler/rustc_codegen_ssa/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub use self::builder::{BuilderMethods, OverflowOp};
pub use self::consts::ConstMethods;
pub use self::coverageinfo::{CoverageInfoBuilderMethods, CoverageInfoMethods};
pub use self::debuginfo::{DebugInfoBuilderMethods, DebugInfoMethods};
pub use self::declare::{DeclareMethods, PreDefineMethods};
pub use self::declare::PreDefineMethods;
pub use self::intrinsic::IntrinsicCallMethods;
pub use self::misc::MiscMethods;
pub use self::statics::{StaticBuilderMethods, StaticMethods};
Expand All @@ -60,7 +60,6 @@ pub trait CodegenMethods<'tcx>:
+ StaticMethods
+ CoverageInfoMethods
+ DebugInfoMethods<'tcx>
+ DeclareMethods<'tcx>
+ AsmMethods
+ PreDefineMethods<'tcx>
+ HasParamEnv<'tcx>
Expand All @@ -77,7 +76,6 @@ impl<'tcx, T> CodegenMethods<'tcx> for T where
+ StaticMethods
+ CoverageInfoMethods
+ DebugInfoMethods<'tcx>
+ DeclareMethods<'tcx>
+ AsmMethods
+ PreDefineMethods<'tcx>
+ HasParamEnv<'tcx>
Expand Down