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

Querify entry_fn #57573

Merged
merged 2 commits into from
Jan 19, 2019
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
1 change: 1 addition & 0 deletions src/librustc/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,7 @@ define_dep_nodes!( <'tcx>
[] CheckImplItemWellFormed(DefId),
[] ReachableNonGenerics(CrateNum),
[] NativeLibraries(CrateNum),
[] EntryFn(CrateNum),
[] PluginRegistrarFn(CrateNum),
[] ProcMacroDeclsStatic(CrateNum),
[input] CrateDisambiguator(CrateNum),
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/dead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ fn create_and_seed_worklist<'a, 'tcx>(
}
}).chain(
// Seed entry point
tcx.sess.entry_fn.borrow().map(|(id, _, _)| id)
tcx.entry_fn(LOCAL_CRATE).map(|(def_id, _)| tcx.hir().as_local_node_id(def_id).unwrap())
).collect::<Vec<_>>();

// Seed implemented trait items
Expand Down
77 changes: 46 additions & 31 deletions src/librustc/middle/entry.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use hir::map as hir_map;
use hir::def_id::{CRATE_DEF_INDEX};
use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE};
use session::{config, Session};
use session::config::EntryFnType;
use syntax::ast::NodeId;
Expand All @@ -8,6 +8,8 @@ use syntax::entry::EntryPointType;
use syntax_pos::Span;
use hir::{Item, ItemKind, ImplItem, TraitItem};
use hir::itemlikevisit::ItemLikeVisitor;
use ty::TyCtxt;
use ty::query::Providers;

struct EntryContext<'a, 'tcx: 'a> {
session: &'a Session,
Expand Down Expand Up @@ -45,36 +47,34 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for EntryContext<'a, 'tcx> {
}
}

pub fn find_entry_point(session: &Session,
hir_map: &hir_map::Map<'_>,
crate_name: &str) {
let any_exe = session.crate_types.borrow().iter().any(|ty| {
fn entry_fn(tcx: TyCtxt<'_, '_, '_>, cnum: CrateNum) -> Option<(DefId, EntryFnType)> {
assert_eq!(cnum, LOCAL_CRATE);

let any_exe = tcx.sess.crate_types.borrow().iter().any(|ty| {
*ty == config::CrateType::Executable
});
if !any_exe {
// No need to find a main function
session.entry_fn.set(None);
return
return None;
}

// If the user wants no main function at all, then stop here.
if attr::contains_name(&hir_map.krate().attrs, "no_main") {
session.entry_fn.set(None);
return
if attr::contains_name(&tcx.hir().krate().attrs, "no_main") {
return None;
}

let mut ctxt = EntryContext {
session,
map: hir_map,
session: tcx.sess,
map: tcx.hir(),
main_fn: None,
attr_main_fn: None,
start_fn: None,
non_main_fns: Vec::new(),
};

hir_map.krate().visit_all_item_likes(&mut ctxt);
tcx.hir().krate().visit_all_item_likes(&mut ctxt);

configure_main(&mut ctxt, crate_name);
configure_main(tcx, &ctxt)
}

// Beware, this is duplicated in `libsyntax/entry.rs`, so make sure to keep
Expand Down Expand Up @@ -135,43 +135,58 @@ fn find_item(item: &Item, ctxt: &mut EntryContext<'_, '_>, at_root: bool) {
.span_label(item.span, "multiple `start` functions")
.emit();
}
},
EntryPointType::None => ()
}
EntryPointType::None => (),
}
}

fn configure_main(this: &mut EntryContext<'_, '_>, crate_name: &str) {
if let Some((node_id, span)) = this.start_fn {
this.session.entry_fn.set(Some((node_id, span, EntryFnType::Start)));
} else if let Some((node_id, span)) = this.attr_main_fn {
this.session.entry_fn.set(Some((node_id, span, EntryFnType::Main)));
} else if let Some((node_id, span)) = this.main_fn {
this.session.entry_fn.set(Some((node_id, span, EntryFnType::Main)));
fn configure_main(
tcx: TyCtxt<'_, '_, '_>,
visitor: &EntryContext<'_, '_>,
) -> Option<(DefId, EntryFnType)> {
if let Some((node_id, _)) = visitor.start_fn {
Some((tcx.hir().local_def_id(node_id), EntryFnType::Start))
} else if let Some((node_id, _)) = visitor.attr_main_fn {
Some((tcx.hir().local_def_id(node_id), EntryFnType::Main))
} else if let Some((node_id, _)) = visitor.main_fn {
Some((tcx.hir().local_def_id(node_id), EntryFnType::Main))
} else {
// No main function
this.session.entry_fn.set(None);
let mut err = struct_err!(this.session, E0601,
"`main` function not found in crate `{}`", crate_name);
if !this.non_main_fns.is_empty() {
let mut err = struct_err!(tcx.sess, E0601,
"`main` function not found in crate `{}`", tcx.crate_name(LOCAL_CRATE));
if !visitor.non_main_fns.is_empty() {
// There were some functions named 'main' though. Try to give the user a hint.
err.note("the main function must be defined at the crate level \
but you have one or more functions named 'main' that are not \
defined at the crate level. Either move the definition or \
attach the `#[main]` attribute to override this behavior.");
for &(_, span) in &this.non_main_fns {
for &(_, span) in &visitor.non_main_fns {
err.span_note(span, "here is a function named 'main'");
}
err.emit();
this.session.abort_if_errors();
tcx.sess.abort_if_errors();
} else {
if let Some(ref filename) = this.session.local_crate_source_file {
if let Some(ref filename) = tcx.sess.local_crate_source_file {
err.note(&format!("consider adding a `main` function to `{}`", filename.display()));
}
if this.session.teach(&err.get_code().unwrap()) {
if tcx.sess.teach(&err.get_code().unwrap()) {
err.note("If you don't know the basics of Rust, you can go look to the Rust Book \
to get started: https://doc.rust-lang.org/book/");
}
err.emit();
}

None
}
}

pub fn find_entry_point(tcx: TyCtxt<'_, '_, '_>) -> Option<(DefId, EntryFnType)> {
tcx.entry_fn(LOCAL_CRATE)
}

pub fn provide(providers: &mut Providers<'_>) {
*providers = Providers {
entry_fn,
..*providers
};
}
8 changes: 4 additions & 4 deletions src/librustc/session/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -649,15 +649,15 @@ impl Options {
}
}

// The type of entry function, so
// users can have their own entry
// functions
#[derive(Copy, Clone, PartialEq)]
// The type of entry function, so users can have their own entry functions
#[derive(Copy, Clone, PartialEq, Hash, Debug)]
pub enum EntryFnType {
Main,
Start,
}

impl_stable_hash_via_hash!(EntryFnType);

#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug)]
pub enum CrateType {
Executable,
Expand Down
4 changes: 0 additions & 4 deletions src/librustc/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,6 @@ pub struct Session {
/// This is `None` if the host and target are the same.
pub target_tlib_path: Option<SearchPath>,
pub parse_sess: ParseSess,
/// For a library crate, this is always none
pub entry_fn: Once<Option<(NodeId, Span, config::EntryFnType)>>,
pub sysroot: PathBuf,
/// The name of the root source file of the crate, in the local file system.
/// `None` means that there is no source file.
Expand Down Expand Up @@ -1173,8 +1171,6 @@ pub fn build_session_(
host_tlib_path,
target_tlib_path,
parse_sess: p_s,
// For a library crate, this is always none
entry_fn: Once::new(),
sysroot,
local_crate_source_file,
working_dir,
Expand Down
6 changes: 6 additions & 0 deletions src/librustc/ty/query/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::foreign_modules<'tcx> {
}
}

impl<'tcx> QueryDescription<'tcx> for queries::entry_fn<'tcx> {
fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
"looking up the entry function of a crate".into()
}
}

impl<'tcx> QueryDescription<'tcx> for queries::plugin_registrar_fn<'tcx> {
fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
"looking up the plugin registrar for a crate".into()
Expand Down
5 changes: 4 additions & 1 deletion src/librustc/ty/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use mir::mono::CodegenUnit;
use mir;
use mir::interpret::GlobalId;
use session::{CompileResult, CrateDisambiguator};
use session::config::OutputFilenames;
use session::config::{EntryFnType, OutputFilenames};
use traits::{self, Vtable};
use traits::query::{
CanonicalPredicateGoal, CanonicalProjectionGoal,
Expand Down Expand Up @@ -476,6 +476,9 @@ define_queries! { <'tcx>

[] fn foreign_modules: ForeignModules(CrateNum) -> Lrc<Vec<ForeignModule>>,

/// Identifies the entry-point (e.g. the `main` function) for a given
/// crate, returning `None` if there is no entry point (such as for library crates).
[] fn entry_fn: EntryFn(CrateNum) -> Option<(DefId, EntryFnType)>,
Xanewok marked this conversation as resolved.
Show resolved Hide resolved
[] fn plugin_registrar_fn: PluginRegistrarFn(CrateNum) -> Option<DefId>,
[] fn proc_macro_decls_static: ProcMacroDeclsStatic(CrateNum) -> Option<DefId>,
[] fn crate_disambiguator: CrateDisambiguator(CrateNum) -> CrateDisambiguator,
Expand Down
1 change: 1 addition & 0 deletions src/librustc/ty/query/plumbing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1362,6 +1362,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
DepKind::CheckImplItemWellFormed => { force!(check_impl_item_well_formed, def_id!()); }
DepKind::ReachableNonGenerics => { force!(reachable_non_generics, krate!()); }
DepKind::NativeLibraries => { force!(native_libraries, krate!()); }
DepKind::EntryFn => { force!(entry_fn, krate!()); }
DepKind::PluginRegistrarFn => { force!(plugin_registrar_fn, krate!()); }
DepKind::ProcMacroDeclsStatic => { force!(proc_macro_decls_static, krate!()); }
DepKind::CrateDisambiguator => { force!(crate_disambiguator, krate!()); }
Expand Down
7 changes: 3 additions & 4 deletions src/librustc_codegen_llvm/debuginfo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use llvm;
use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilder, DISubprogram, DIArray, DIFlags,
DILexicalBlock};
use rustc::hir::CodegenFnAttrFlags;
use rustc::hir::def_id::{DefId, CrateNum};
use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE};
use rustc::ty::subst::{Substs, UnpackedKind};

use abi::Abi;
Expand Down Expand Up @@ -290,9 +290,8 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {

let mut flags = DIFlags::FlagPrototyped;

let local_id = self.tcx().hir().as_local_node_id(def_id);
if let Some((id, _, _)) = *self.sess().entry_fn.borrow() {
if local_id == Some(id) {
if let Some((id, _)) = self.tcx.entry_fn(LOCAL_CRATE) {
if id == def_id {
flags |= DIFlags::FlagMainSubprogram;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_codegen_ssa/back/symbol_export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
})
.collect();

if tcx.sess.entry_fn.borrow().is_some() {
if tcx.entry_fn(LOCAL_CRATE).is_some() {
let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new("main"));
Xanewok marked this conversation as resolved.
Show resolved Hide resolved

symbols.push((exported_symbol, SymbolExportLevel::C));
Expand Down
8 changes: 3 additions & 5 deletions src/librustc_codegen_ssa/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -441,10 +441,8 @@ pub fn codegen_instance<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
pub fn maybe_create_entry_wrapper<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
cx: &'a Bx::CodegenCx
) {
let (main_def_id, span) = match *cx.sess().entry_fn.borrow() {
Some((id, span, _)) => {
(cx.tcx().hir().local_def_id(id), span)
}
let (main_def_id, span) = match cx.tcx().entry_fn(LOCAL_CRATE) {
Some((def_id, _)) => { (def_id, cx.tcx().def_span(def_id)) },
None => return,
};

Expand All @@ -458,7 +456,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(

let main_llfn = cx.get_fn(instance);

let et = cx.sess().entry_fn.get().map(|e| e.2);
let et = cx.tcx().entry_fn(LOCAL_CRATE).map(|e| e.1);
match et {
Some(EntryFnType::Main) => create_entry_fn::<Bx>(cx, span, main_llfn, main_def_id, true),
Some(EntryFnType::Start) => create_entry_fn::<Bx>(cx, span, main_llfn, main_def_id, false),
Expand Down
9 changes: 4 additions & 5 deletions src/librustc_codegen_utils/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ extern crate syntax_pos;
#[macro_use] extern crate rustc_data_structures;

use rustc::ty::TyCtxt;
use rustc::hir::def_id::LOCAL_CRATE;

pub mod link;
pub mod codegen_backend;
Expand All @@ -42,11 +43,9 @@ pub mod symbol_names_test;
/// that actually test that compilation succeeds without
/// reporting an error.
pub fn check_for_rustc_errors_attr(tcx: TyCtxt) {
if let Some((id, span, _)) = *tcx.sess.entry_fn.borrow() {
let main_def_id = tcx.hir().local_def_id(id);

if tcx.has_attr(main_def_id, "rustc_error") {
tcx.sess.span_fatal(span, "compilation successful");
if let Some((def_id, _)) = tcx.entry_fn(LOCAL_CRATE) {
if tcx.has_attr(def_id, "rustc_error") {
tcx.sess.span_fatal(tcx.def_span(def_id), "compilation successful");
}
}
}
9 changes: 5 additions & 4 deletions src/librustc_driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1174,6 +1174,7 @@ pub fn default_provide(providers: &mut ty::query::Providers) {
rustc_passes::provide(providers);
rustc_traits::provide(providers);
middle::region::provide(providers);
middle::entry::provide(providers);
cstore::provide(providers);
lint::provide(providers);
}
Expand Down Expand Up @@ -1210,10 +1211,6 @@ where
rustc_incremental::load_query_result_cache(sess)
});

time(sess, "looking for entry point", || {
middle::entry::find_entry_point(sess, &hir_map, name)
});

let mut local_providers = ty::query::Providers::default();
default_provide(&mut local_providers);
codegen_backend.provide(&mut local_providers);
Expand Down Expand Up @@ -1243,6 +1240,10 @@ where
// tcx available.
time(sess, "dep graph tcx init", || rustc_incremental::dep_graph_tcx_init(tcx));

time(sess, "looking for entry point", || {
middle::entry::find_entry_point(tcx)
});

time(sess, "looking for plugin registrar", || {
plugin::build::find_plugin_registrar(tcx)
});
Expand Down
Loading