about summary refs log tree commit diff
path: root/compiler/rustc_plugin_impl
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-08-30 15:57:57 +0000
committerbors <bors@rust-lang.org>2020-08-30 15:57:57 +0000
commit85fbf49ce0e2274d0acf798f6e703747674feec3 (patch)
tree158a05eb3f204a8e72939b58427d0c2787a4eade /compiler/rustc_plugin_impl
parentdb534b3ac286cf45688c3bbae6aa6e77439e52d2 (diff)
parent9e5f7d5631b8f4009ac1c693e585d4b7108d4275 (diff)
downloadrust-85fbf49ce0e2274d0acf798f6e703747674feec3.tar.gz
rust-85fbf49ce0e2274d0acf798f6e703747674feec3.zip
Auto merge of #74862 - mark-i-m:mv-compiler, r=petrochenkov
Move almost all compiler crates to compiler/

This PR implements https://github.com/rust-lang/compiler-team/issues/336 and moves all `rustc_*` crates from `src` to the new `compiler` directory.

`librustc_foo` directories are renamed to `rustc_foo`.
`src` directories are introduced inside `rustc_*` directories to mirror the scheme already use for `library` crates.
Diffstat (limited to 'compiler/rustc_plugin_impl')
-rw-r--r--compiler/rustc_plugin_impl/Cargo.toml19
-rw-r--r--compiler/rustc_plugin_impl/src/build.rs62
-rw-r--r--compiler/rustc_plugin_impl/src/lib.rs25
-rw-r--r--compiler/rustc_plugin_impl/src/load.rs99
4 files changed, 205 insertions, 0 deletions
diff --git a/compiler/rustc_plugin_impl/Cargo.toml b/compiler/rustc_plugin_impl/Cargo.toml
new file mode 100644
index 00000000000..500d13a8c16
--- /dev/null
+++ b/compiler/rustc_plugin_impl/Cargo.toml
@@ -0,0 +1,19 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "rustc_plugin_impl"
+version = "0.0.0"
+build = false
+edition = "2018"
+
+[lib]
+doctest = false
+
+[dependencies]
+rustc_middle = { path = "../rustc_middle" }
+rustc_errors = { path = "../rustc_errors" }
+rustc_hir = { path = "../rustc_hir" }
+rustc_lint = { path = "../rustc_lint" }
+rustc_metadata = { path = "../rustc_metadata" }
+rustc_ast = { path = "../rustc_ast" }
+rustc_session = { path = "../rustc_session" }
+rustc_span = { path = "../rustc_span" }
diff --git a/compiler/rustc_plugin_impl/src/build.rs b/compiler/rustc_plugin_impl/src/build.rs
new file mode 100644
index 00000000000..d16dd701a12
--- /dev/null
+++ b/compiler/rustc_plugin_impl/src/build.rs
@@ -0,0 +1,62 @@
+//! Used by `rustc` when compiling a plugin crate.
+
+use rustc_hir as hir;
+use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use rustc_hir::itemlikevisit::ItemLikeVisitor;
+use rustc_middle::ty::query::Providers;
+use rustc_middle::ty::TyCtxt;
+use rustc_span::symbol::sym;
+use rustc_span::Span;
+
+struct RegistrarFinder<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    registrars: Vec<(hir::HirId, Span)>,
+}
+
+impl<'v, 'tcx> ItemLikeVisitor<'v> for RegistrarFinder<'tcx> {
+    fn visit_item(&mut self, item: &hir::Item<'_>) {
+        if let hir::ItemKind::Fn(..) = item.kind {
+            if self.tcx.sess.contains_name(&item.attrs, sym::plugin_registrar) {
+                self.registrars.push((item.hir_id, item.span));
+            }
+        }
+    }
+
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
+
+    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
+}
+
+/// Finds the function marked with `#[plugin_registrar]`, if any.
+pub fn find_plugin_registrar(tcx: TyCtxt<'_>) -> Option<DefId> {
+    tcx.plugin_registrar_fn(LOCAL_CRATE)
+}
+
+fn plugin_registrar_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<DefId> {
+    assert_eq!(cnum, LOCAL_CRATE);
+
+    let mut finder = RegistrarFinder { tcx, registrars: Vec::new() };
+    tcx.hir().krate().visit_all_item_likes(&mut finder);
+
+    match finder.registrars.len() {
+        0 => None,
+        1 => {
+            let (hir_id, _) = finder.registrars.pop().unwrap();
+            Some(tcx.hir().local_def_id(hir_id).to_def_id())
+        }
+        _ => {
+            let diagnostic = tcx.sess.diagnostic();
+            let mut e = diagnostic.struct_err("multiple plugin registration functions found");
+            for &(_, span) in &finder.registrars {
+                e.span_note(span, "one is here");
+            }
+            e.emit();
+            diagnostic.abort_if_errors();
+            unreachable!();
+        }
+    }
+}
+
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers { plugin_registrar_fn, ..*providers };
+}
diff --git a/compiler/rustc_plugin_impl/src/lib.rs b/compiler/rustc_plugin_impl/src/lib.rs
new file mode 100644
index 00000000000..1eb65dd96ba
--- /dev/null
+++ b/compiler/rustc_plugin_impl/src/lib.rs
@@ -0,0 +1,25 @@
+//! Infrastructure for compiler plugins.
+//!
+//! Plugins are a deprecated way to extend the behavior of `rustc` in various ways.
+//!
+//! See the [`plugin`
+//! feature](https://doc.rust-lang.org/nightly/unstable-book/language-features/plugin.html)
+//! of the Unstable Book for some examples.
+
+#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
+#![feature(nll)]
+#![recursion_limit = "256"]
+
+use rustc_lint::LintStore;
+
+pub mod build;
+pub mod load;
+
+/// Structure used to register plugins.
+///
+/// A plugin registrar function takes an `&mut Registry` and should call
+/// methods to register its plugins.
+pub struct Registry<'a> {
+    /// The `LintStore` allows plugins to register new lints.
+    pub lint_store: &'a mut LintStore,
+}
diff --git a/compiler/rustc_plugin_impl/src/load.rs b/compiler/rustc_plugin_impl/src/load.rs
new file mode 100644
index 00000000000..687f7db221f
--- /dev/null
+++ b/compiler/rustc_plugin_impl/src/load.rs
@@ -0,0 +1,99 @@
+//! Used by `rustc` when loading a plugin.
+
+use crate::Registry;
+use rustc_ast::Crate;
+use rustc_errors::struct_span_err;
+use rustc_metadata::locator;
+use rustc_middle::middle::cstore::MetadataLoader;
+use rustc_session::Session;
+use rustc_span::symbol::{sym, Ident};
+use rustc_span::Span;
+
+use std::borrow::ToOwned;
+use std::env;
+use std::mem;
+use std::path::PathBuf;
+
+/// Pointer to a registrar function.
+type PluginRegistrarFn = fn(&mut Registry<'_>);
+
+fn call_malformed_plugin_attribute(sess: &Session, span: Span) {
+    struct_span_err!(sess, span, E0498, "malformed `plugin` attribute")
+        .span_label(span, "malformed attribute")
+        .emit();
+}
+
+/// Read plugin metadata and dynamically load registrar functions.
+pub fn load_plugins(
+    sess: &Session,
+    metadata_loader: &dyn MetadataLoader,
+    krate: &Crate,
+) -> Vec<PluginRegistrarFn> {
+    let mut plugins = Vec::new();
+
+    for attr in &krate.attrs {
+        if !sess.check_name(attr, sym::plugin) {
+            continue;
+        }
+
+        for plugin in attr.meta_item_list().unwrap_or_default() {
+            match plugin.ident() {
+                Some(ident) if plugin.is_word() => {
+                    load_plugin(&mut plugins, sess, metadata_loader, ident)
+                }
+                _ => call_malformed_plugin_attribute(sess, plugin.span()),
+            }
+        }
+    }
+
+    plugins
+}
+
+fn load_plugin(
+    plugins: &mut Vec<PluginRegistrarFn>,
+    sess: &Session,
+    metadata_loader: &dyn MetadataLoader,
+    ident: Ident,
+) {
+    let (lib, disambiguator) =
+        locator::find_plugin_registrar(sess, metadata_loader, ident.span, ident.name);
+    let symbol = sess.generate_plugin_registrar_symbol(disambiguator);
+    let fun = dylink_registrar(sess, ident.span, lib, symbol);
+    plugins.push(fun);
+}
+
+// Dynamically link a registrar function into the compiler process.
+fn dylink_registrar(
+    sess: &Session,
+    span: Span,
+    path: PathBuf,
+    symbol: String,
+) -> PluginRegistrarFn {
+    use rustc_metadata::dynamic_lib::DynamicLibrary;
+
+    // Make sure the path contains a / or the linker will search for it.
+    let path = env::current_dir().unwrap().join(&path);
+
+    let lib = match DynamicLibrary::open(&path) {
+        Ok(lib) => lib,
+        // this is fatal: there are almost certainly macros we need
+        // inside this crate, so continue would spew "macro undefined"
+        // errors
+        Err(err) => sess.span_fatal(span, &err),
+    };
+
+    unsafe {
+        let registrar = match lib.symbol(&symbol) {
+            Ok(registrar) => mem::transmute::<*mut u8, PluginRegistrarFn>(registrar),
+            // again fatal if we can't register macros
+            Err(err) => sess.span_fatal(span, &err),
+        };
+
+        // Intentionally leak the dynamic library. We can't ever unload it
+        // since the library can make things that will live arbitrarily long
+        // (e.g., an @-box cycle or a thread).
+        mem::forget(lib);
+
+        registrar
+    }
+}