about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-06-09 15:52:07 -0700
committerbors <bors@rust-lang.org>2014-06-09 15:52:07 -0700
commit0ea7aa30cc864d00fc30b9ba610f2daefab4e850 (patch)
tree2f3216efe5cc25851595c14d803dc69738030a72 /src
parentb6146e652ae7f6d373d55dd021dc50cb00e0caf8 (diff)
parentdeecda6a94b31489045d420f16840a72c44af7e1 (diff)
downloadrust-0ea7aa30cc864d00fc30b9ba610f2daefab4e850.tar.gz
rust-0ea7aa30cc864d00fc30b9ba610f2daefab4e850.zip
auto merge of #14554 : kmcallister/rust/plugin_registrar, r=cmr
This implements the design in rust-lang/rfcs#86.  It shouldn't be merged until that RFC is accepted, but it would be great if somebody has time to review the code before then.
Diffstat (limited to 'src')
-rw-r--r--src/compiletest/compiletest.rs10
-rw-r--r--src/doc/rust.md7
-rw-r--r--src/liballoc/lib.rs12
-rw-r--r--src/libcollections/lib.rs16
-rw-r--r--src/libflate/lib.rs3
-rw-r--r--src/libfourcc/lib.rs20
-rw-r--r--src/libgetopts/lib.rs3
-rw-r--r--src/libgreen/lib.rs6
-rw-r--r--src/libhexfloat/lib.rs20
-rw-r--r--src/liblog/lib.rs2
-rw-r--r--src/liblog/macros.rs12
-rw-r--r--src/librand/lib.rs19
-rw-r--r--src/libregex/lib.rs12
-rw-r--r--src/libregex/re.rs26
-rw-r--r--src/libregex/test/mod.rs2
-rw-r--r--src/libregex_macros/lib.rs17
-rw-r--r--src/librustc/driver/driver.rs66
-rw-r--r--src/librustc/driver/session.rs4
-rw-r--r--src/librustc/front/feature_gate.rs9
-rw-r--r--src/librustc/front/std_inject.rs2
-rw-r--r--src/librustc/front/test.rs3
-rw-r--r--src/librustc/lib.rs7
-rw-r--r--src/librustc/metadata/common.rs2
-rw-r--r--src/librustc/metadata/creader.rs24
-rw-r--r--src/librustc/metadata/cstore.rs3
-rw-r--r--src/librustc/metadata/decoder.rs4
-rw-r--r--src/librustc/metadata/encoder.rs40
-rw-r--r--src/librustc/plugin/build.rs (renamed from src/libsyntax/ext/registrar.rs)37
-rw-r--r--src/librustc/plugin/load.rs145
-rw-r--r--src/librustc/plugin/mod.rs64
-rw-r--r--src/librustc/plugin/registry.rs70
-rw-r--r--src/librustdoc/core.rs5
-rw-r--r--src/librustdoc/lib.rs10
-rw-r--r--src/librustdoc/test.rs3
-rw-r--r--src/librustrt/lib.rs10
-rw-r--r--src/libserialize/lib.rs6
-rw-r--r--src/libstd/lib.rs3
-rw-r--r--src/libsync/lib.rs5
-rw-r--r--src/libsyntax/ext/base.rs19
-rw-r--r--src/libsyntax/ext/expand.rs152
-rw-r--r--src/libsyntax/lib.rs8
-rw-r--r--src/libterm/lib.rs3
-rw-r--r--src/libtime/lib.rs4
-rw-r--r--src/test/auxiliary/issue-13560-3.rs4
-rw-r--r--src/test/auxiliary/logging_right_crate.rs2
-rw-r--r--src/test/auxiliary/macro_crate_test.rs21
-rw-r--r--src/test/auxiliary/plugin_crate_outlive_expansion_phase.rs (renamed from src/test/auxiliary/macro_crate_outlive_expansion_phase.rs)11
-rw-r--r--src/test/auxiliary/syntax-extension-with-dll-deps-2.rs18
-rw-r--r--src/test/auxiliary/weak-lang-items.rs2
-rw-r--r--src/test/bench/shootout-chameneos-redux.rs2
-rw-r--r--src/test/bench/shootout-meteor.rs2
-rw-r--r--src/test/bench/shootout-regex-dna.rs2
-rw-r--r--src/test/bench/shootout-spectralnorm.rs2
-rw-r--r--src/test/bench/shootout-threadring.rs2
-rw-r--r--src/test/compile-fail-fulldeps/gated-phase.rs2
-rw-r--r--src/test/compile-fail-fulldeps/macro-crate-unexported-macro.rs2
-rw-r--r--src/test/compile-fail-fulldeps/macro-crate-unknown-crate.rs2
-rw-r--r--src/test/compile-fail-fulldeps/phase-syntax-doesnt-resolve.rs2
-rw-r--r--src/test/compile-fail-fulldeps/syntax-extension-fourcc-bad-len.rs2
-rw-r--r--src/test/compile-fail-fulldeps/syntax-extension-fourcc-invalid-endian.rs2
-rw-r--r--src/test/compile-fail-fulldeps/syntax-extension-fourcc-non-ascii-str.rs2
-rw-r--r--src/test/compile-fail-fulldeps/syntax-extension-fourcc-non-literal.rs2
-rw-r--r--src/test/compile-fail-fulldeps/syntax-extension-fourcc-unsupported-literal.rs2
-rw-r--r--src/test/compile-fail-fulldeps/syntax-extension-hexfloat-bad-lits.rs2
-rw-r--r--src/test/compile-fail-fulldeps/syntax-extension-hexfloat-bad-types.rs2
-rw-r--r--src/test/compile-fail-fulldeps/syntax-extension-regex-invalid.rs2
-rw-r--r--src/test/compile-fail-fulldeps/syntax-extension-regex-unused-static.rs2
-rw-r--r--src/test/compile-fail-fulldeps/syntax-extension-regex-unused.rs2
-rw-r--r--src/test/compile-fail/gated-plugin_registrar.rs (renamed from src/test/compile-fail/gated-macro_registrar.rs)4
-rw-r--r--src/test/compile-fail/multiple-plugin-registrars.rs (renamed from src/test/compile-fail/multiple-macro-registrars.rs)8
-rw-r--r--src/test/run-fail/rt-set-exit-status-fail.rs2
-rw-r--r--src/test/run-fail/rt-set-exit-status-fail2.rs2
-rw-r--r--src/test/run-fail/rt-set-exit-status.rs2
-rw-r--r--src/test/run-make/lto-syntax-extension/main.rs2
-rw-r--r--src/test/run-pass-fulldeps/macro-crate-outlive-expansion-phase.rs6
-rw-r--r--src/test/run-pass-fulldeps/macro-crate.rs2
-rw-r--r--src/test/run-pass-fulldeps/phase-syntax-link-does-resolve.rs2
-rw-r--r--src/test/run-pass-fulldeps/syntax-extension-fourcc.rs2
-rw-r--r--src/test/run-pass-fulldeps/syntax-extension-hexfloat.rs2
-rw-r--r--src/test/run-pass-fulldeps/syntax-extension-with-dll-deps.rs2
-rw-r--r--src/test/run-pass/capturing-logging.rs2
-rw-r--r--src/test/run-pass/conditional-debug-macro-off.rs2
-rw-r--r--src/test/run-pass/deprecated-phase-syntax.rs19
-rw-r--r--src/test/run-pass/issue-14456.rs2
-rw-r--r--src/test/run-pass/logging-enabled-debug.rs2
-rw-r--r--src/test/run-pass/logging-enabled.rs2
-rw-r--r--src/test/run-pass/logging-separate-lines.rs2
-rw-r--r--src/test/run-pass/macro-crate-def-only.rs2
-rw-r--r--src/test/run-pass/macro-export-inner-module.rs2
-rw-r--r--src/test/run-pass/phase-use-ignored.rs2
-rw-r--r--src/test/run-pass/tcp-stress.rs2
91 files changed, 666 insertions, 400 deletions
diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs
index 8fcad94ee1c..de0ca4971f5 100644
--- a/src/compiletest/compiletest.rs
+++ b/src/compiletest/compiletest.rs
@@ -18,11 +18,17 @@
 
 extern crate test;
 extern crate getopts;
-#[phase(link, syntax)]
-extern crate log;
 extern crate green;
 extern crate rustuv;
 
+#[cfg(stage0)]
+#[phase(syntax, link)]
+extern crate log;
+
+#[cfg(not(stage0))]
+#[phase(plugin, link)]
+extern crate log;
+
 extern crate regex;
 
 use std::os;
diff --git a/src/doc/rust.md b/src/doc/rust.md
index 619e24af360..35d356bb1b5 100644
--- a/src/doc/rust.md
+++ b/src/doc/rust.md
@@ -1819,9 +1819,8 @@ type int8_t = i8;
 
 ### Function-only attributes
 
-- `macro_registrar` - when using loadable syntax extensions, mark this
-  function as the registration point for the current crate's syntax
-  extensions.
+- `plugin_registrar` - mark this function as the registration point for
+  compiler plugins, such as loadable syntax extensions.
 - `main` - indicates that this function should be passed to the entry point,
   rather than the function in the crate root named `main`.
 - `start` - indicates that this function should be used as the entry point,
@@ -4098,7 +4097,7 @@ that demonstrates all four of them:
 
 ~~~~
 #![feature(phase)]
-#[phase(syntax, link)] extern crate log;
+#[phase(plugin, link)] extern crate log;
 
 fn main() {
     error!("This is an error log")
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index ca7ed6f4ba0..7e2c9a75fad 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -70,8 +70,14 @@
 #![no_std]
 #![feature(phase)]
 
+#[cfg(stage0)]
 #[phase(syntax, link)]
 extern crate core;
+
+#[cfg(not(stage0))]
+#[phase(plugin, link)]
+extern crate core;
+
 extern crate libc;
 
 
@@ -80,8 +86,10 @@ extern crate libc;
 #[cfg(test)] extern crate debug;
 #[cfg(test)] extern crate sync;
 #[cfg(test)] extern crate native;
-#[cfg(test)] #[phase(syntax, link)] extern crate std;
-#[cfg(test)] #[phase(syntax, link)] extern crate log;
+#[cfg(test, stage0)] #[phase(syntax, link)] extern crate std;
+#[cfg(test, stage0)] #[phase(syntax, link)] extern crate log;
+#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate std;
+#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate log;
 
 // Heaps provided for low-level allocation strategies
 
diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs
index 602ecf39a83..a114755a0ed 100644
--- a/src/libcollections/lib.rs
+++ b/src/libcollections/lib.rs
@@ -23,14 +23,24 @@
 #![feature(macro_rules, managed_boxes, default_type_params, phase, globs)]
 #![no_std]
 
-#[phase(syntax, link)] extern crate core;
 extern crate alloc;
 
+#[cfg(stage0)]
+#[phase(syntax, link)]
+extern crate core;
+
+#[cfg(not(stage0))]
+#[phase(plugin, link)]
+extern crate core;
+
 #[cfg(test)] extern crate native;
 #[cfg(test)] extern crate test;
 #[cfg(test)] extern crate debug;
-#[cfg(test)] #[phase(syntax, link)] extern crate std;
-#[cfg(test)] #[phase(syntax, link)] extern crate log;
+
+#[cfg(test, stage0)] #[phase(syntax, link)] extern crate std;
+#[cfg(test, stage0)] #[phase(syntax, link)] extern crate log;
+#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate std;
+#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate log;
 
 use core::prelude::*;
 
diff --git a/src/libflate/lib.rs b/src/libflate/lib.rs
index 8bfd2d867c1..8d8fe8ffe8c 100644
--- a/src/libflate/lib.rs
+++ b/src/libflate/lib.rs
@@ -28,7 +28,8 @@ Simple [DEFLATE][def]-based compression. This is a wrapper around the
 #![feature(phase)]
 #![deny(deprecated_owned_vector)]
 
-#[cfg(test)] #[phase(syntax, link)] extern crate log;
+#[cfg(test, stage0)] #[phase(syntax, link)] extern crate log;
+#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate log;
 
 extern crate libc;
 
diff --git a/src/libfourcc/lib.rs b/src/libfourcc/lib.rs
index 194de7b2f4a..694fe7d0f48 100644
--- a/src/libfourcc/lib.rs
+++ b/src/libfourcc/lib.rs
@@ -22,7 +22,7 @@ to be `big`, i.e. left-to-right order. It returns a u32.
 To load the extension and use it:
 
 ```rust,ignore
-#[phase(syntax)]
+#[phase(plugin)]
 extern crate fourcc;
 
 fn main() {
@@ -48,29 +48,25 @@ fn main() {
        html_root_url = "http://doc.rust-lang.org/")]
 
 #![deny(deprecated_owned_vector)]
-#![feature(macro_registrar, managed_boxes)]
+#![feature(plugin_registrar, managed_boxes)]
 
 extern crate syntax;
+extern crate rustc;
 
 use syntax::ast;
-use syntax::ast::Name;
 use syntax::attr::contains;
 use syntax::codemap::{Span, mk_sp};
 use syntax::ext::base;
-use syntax::ext::base::{SyntaxExtension, BasicMacroExpander, NormalTT, ExtCtxt, MacExpr};
+use syntax::ext::base::{ExtCtxt, MacExpr};
 use syntax::ext::build::AstBuilder;
 use syntax::parse;
 use syntax::parse::token;
 use syntax::parse::token::InternedString;
+use rustc::plugin::Registry;
 
-#[macro_registrar]
-pub fn macro_registrar(register: |Name, SyntaxExtension|) {
-    register(token::intern("fourcc"),
-        NormalTT(box BasicMacroExpander {
-            expander: expand_syntax_ext,
-            span: None,
-        },
-        None));
+#[plugin_registrar]
+pub fn plugin_registrar(reg: &mut Registry) {
+    reg.register_macro("fourcc", expand_syntax_ext);
 }
 
 pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs
index 10584223486..dec62265516 100644
--- a/src/libgetopts/lib.rs
+++ b/src/libgetopts/lib.rs
@@ -91,7 +91,8 @@
 #![deny(deprecated_owned_vector)]
 
 #[cfg(test)] extern crate debug;
-#[cfg(test)] #[phase(syntax, link)] extern crate log;
+#[cfg(test, stage0)] #[phase(syntax, link)] extern crate log;
+#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate log;
 
 use std::cmp::PartialEq;
 use std::result::{Err, Ok};
diff --git a/src/libgreen/lib.rs b/src/libgreen/lib.rs
index 333ac80907f..9748dfbae33 100644
--- a/src/libgreen/lib.rs
+++ b/src/libgreen/lib.rs
@@ -148,7 +148,7 @@
 //!
 //! ```
 //! #![feature(phase)]
-//! #[phase(syntax)] extern crate green;
+//! #[phase(plugin)] extern crate green;
 //!
 //! green_start!(main)
 //!
@@ -211,7 +211,7 @@
 #![allow(visible_private_types)]
 #![deny(deprecated_owned_vector)]
 
-#[cfg(test)] #[phase(syntax, link)] extern crate log;
+#[cfg(test)] #[phase(plugin, link)] extern crate log;
 #[cfg(test)] extern crate rustuv;
 extern crate libc;
 extern crate alloc;
@@ -249,7 +249,7 @@ pub mod task;
 ///
 /// ```
 /// #![feature(phase)]
-/// #[phase(syntax)] extern crate green;
+/// #[phase(plugin)] extern crate green;
 ///
 /// green_start!(main)
 ///
diff --git a/src/libhexfloat/lib.rs b/src/libhexfloat/lib.rs
index ee14f1aaea9..54bc2802b09 100644
--- a/src/libhexfloat/lib.rs
+++ b/src/libhexfloat/lib.rs
@@ -21,7 +21,7 @@ literal.
 To load the extension and use it:
 
 ```rust,ignore
-#[phase(syntax)]
+#[phase(plugin)]
 extern crate hexfloat;
 
 fn main() {
@@ -45,27 +45,23 @@ fn main() {
        html_root_url = "http://doc.rust-lang.org/")]
 
 #![deny(deprecated_owned_vector)]
-#![feature(macro_registrar, managed_boxes)]
+#![feature(plugin_registrar, managed_boxes)]
 
 extern crate syntax;
+extern crate rustc;
 
 use syntax::ast;
-use syntax::ast::Name;
 use syntax::codemap::{Span, mk_sp};
 use syntax::ext::base;
-use syntax::ext::base::{SyntaxExtension, BasicMacroExpander, NormalTT, ExtCtxt, MacExpr};
+use syntax::ext::base::{ExtCtxt, MacExpr};
 use syntax::ext::build::AstBuilder;
 use syntax::parse;
 use syntax::parse::token;
+use rustc::plugin::Registry;
 
-#[macro_registrar]
-pub fn macro_registrar(register: |Name, SyntaxExtension|) {
-    register(token::intern("hexfloat"),
-        NormalTT(box BasicMacroExpander {
-            expander: expand_syntax_ext,
-            span: None,
-        },
-        None));
+#[plugin_registrar]
+pub fn plugin_registrar(reg: &mut Registry) {
+    reg.register_macro("hexfloat", expand_syntax_ext);
 }
 
 //Check if the literal is valid (as LLVM expects),
diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs
index daacf8b3c47..254f9aaf55e 100644
--- a/src/liblog/lib.rs
+++ b/src/liblog/lib.rs
@@ -16,7 +16,7 @@ Utilities for program-wide and customizable logging
 
 ```
 #![feature(phase)]
-#[phase(syntax, link)] extern crate log;
+#[phase(plugin, link)] extern crate log;
 
 fn main() {
     debug!("this is a debug {}", "message");
diff --git a/src/liblog/macros.rs b/src/liblog/macros.rs
index 3bb49c237f1..dba34c42a7e 100644
--- a/src/liblog/macros.rs
+++ b/src/liblog/macros.rs
@@ -22,7 +22,7 @@
 ///
 /// ```
 /// #![feature(phase)]
-/// #[phase(syntax, link)] extern crate log;
+/// #[phase(plugin, link)] extern crate log;
 ///
 /// # fn main() {
 /// log!(log::DEBUG, "this is a debug message");
@@ -51,7 +51,7 @@ macro_rules! log(
 ///
 /// ```
 /// #![feature(phase)]
-/// #[phase(syntax, link)] extern crate log;
+/// #[phase(plugin, link)] extern crate log;
 ///
 /// # fn main() {
 /// # let error = 3;
@@ -69,7 +69,7 @@ macro_rules! error(
 ///
 /// ```
 /// #![feature(phase)]
-/// #[phase(syntax, link)] extern crate log;
+/// #[phase(plugin, link)] extern crate log;
 ///
 /// # fn main() {
 /// # let code = 3;
@@ -87,7 +87,7 @@ macro_rules! warn(
 ///
 /// ```
 /// #![feature(phase)]
-/// #[phase(syntax, link)] extern crate log;
+/// #[phase(plugin, link)] extern crate log;
 ///
 /// # fn main() {
 /// # let ret = 3;
@@ -107,7 +107,7 @@ macro_rules! info(
 ///
 /// ```
 /// #![feature(phase)]
-/// #[phase(syntax, link)] extern crate log;
+/// #[phase(plugin, link)] extern crate log;
 ///
 /// # fn main() {
 /// debug!("x = {x}, y = {y}", x=10, y=20);
@@ -124,7 +124,7 @@ macro_rules! debug(
 ///
 /// ```
 /// #![feature(phase)]
-/// #[phase(syntax, link)] extern crate log;
+/// #[phase(plugin, link)] extern crate log;
 ///
 /// # fn main() {
 /// # struct Point { x: int, y: int }
diff --git a/src/librand/lib.rs b/src/librand/lib.rs
index 7a12dcf9f7f..1f7216fc1a3 100644
--- a/src/librand/lib.rs
+++ b/src/librand/lib.rs
@@ -28,13 +28,28 @@
 #![no_std]
 #![experimental]
 
+#[cfg(stage0)]
 #[phase(syntax, link)]
 extern crate core;
 
+#[cfg(not(stage0))]
+#[phase(plugin, link)]
+extern crate core;
+
+#[cfg(test, stage0)]
+#[phase(syntax, link)] extern crate std;
+
+#[cfg(test, stage0)]
+#[phase(syntax, link)] extern crate log;
+
+#[cfg(test, not(stage0))]
+#[phase(plugin, link)] extern crate std;
+
+#[cfg(test, not(stage0))]
+#[phase(plugin, link)] extern crate log;
+
 #[cfg(test)] extern crate native;
 #[cfg(test)] extern crate debug;
-#[cfg(test)] #[phase(syntax, link)] extern crate std;
-#[cfg(test)] #[phase(syntax, link)] extern crate log;
 
 use core::prelude::*;
 
diff --git a/src/libregex/lib.rs b/src/libregex/lib.rs
index 44c206162ab..61e62a0d105 100644
--- a/src/libregex/lib.rs
+++ b/src/libregex/lib.rs
@@ -65,7 +65,7 @@
 //!
 //! ```rust
 //! #![feature(phase)]
-//! #[phase(syntax)]
+//! #[phase(plugin)]
 //! extern crate regex_macros;
 //! extern crate regex;
 //!
@@ -95,7 +95,7 @@
 //!
 //! ```rust
 //! # #![feature(phase)]
-//! # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+//! # extern crate regex; #[phase(plugin)] extern crate regex_macros;
 //! # fn main() {
 //! let re = regex!(r"(\d{4})-(\d{2})-(\d{2})");
 //! let text = "2012-03-14, 2013-01-01 and 2014-07-05";
@@ -121,7 +121,7 @@
 //!
 //! ```rust
 //! # #![feature(phase)]
-//! # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+//! # extern crate regex; #[phase(plugin)] extern crate regex_macros;
 //! # fn main() {
 //! let re = regex!(r"(?P<y>\d{4})-(?P<m>\d{2})-(?P<d>\d{2})");
 //! let before = "2012-03-14, 2013-01-01 and 2014-07-05";
@@ -168,7 +168,7 @@
 //!
 //! ```rust
 //! # #![feature(phase)]
-//! # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+//! # extern crate regex; #[phase(plugin)] extern crate regex_macros;
 //! # fn main() {
 //! let re = regex!(r"(?i)Δ+");
 //! assert_eq!(re.find("ΔδΔ"), Some((0, 6)));
@@ -181,7 +181,7 @@
 //!
 //! ```rust
 //! # #![feature(phase)]
-//! # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+//! # extern crate regex; #[phase(plugin)] extern crate regex_macros;
 //! # fn main() {
 //! let re = regex!(r"[\pN\p{Greek}\p{Cherokee}]+");
 //! assert_eq!(re.find("abcΔᎠβⅠᏴγδⅡxyz"), Some((3, 23)));
@@ -278,7 +278,7 @@
 //!
 //! ```rust
 //! # #![feature(phase)]
-//! # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+//! # extern crate regex; #[phase(plugin)] extern crate regex_macros;
 //! # fn main() {
 //! let re = regex!(r"(?i)a+(?-i)b+");
 //! let cap = re.captures("AaAaAbbBBBb").unwrap();
diff --git a/src/libregex/re.rs b/src/libregex/re.rs
index a499c1e125d..054cbb0fcd6 100644
--- a/src/libregex/re.rs
+++ b/src/libregex/re.rs
@@ -87,7 +87,7 @@ pub fn is_match(regex: &str, text: &str) -> Result<bool, parse::Error> {
 /// ```rust
 /// #![feature(phase)]
 /// extern crate regex;
-/// #[phase(syntax)] extern crate regex_macros;
+/// #[phase(plugin)] extern crate regex_macros;
 ///
 /// fn main() {
 ///     let re = regex!(r"\d+");
@@ -172,7 +172,7 @@ impl Regex {
     ///
     /// ```rust
     /// # #![feature(phase)]
-    /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+    /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
     /// # fn main() {
     /// let text = "I categorically deny having triskaidekaphobia.";
     /// let matched = regex!(r"\b\w{13}\b").is_match(text);
@@ -197,7 +197,7 @@ impl Regex {
     ///
     /// ```rust
     /// # #![feature(phase)]
-    /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+    /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
     /// # fn main() {
     /// let text = "I categorically deny having triskaidekaphobia.";
     /// let pos = regex!(r"\b\w{13}\b").find(text);
@@ -224,7 +224,7 @@ impl Regex {
     ///
     /// ```rust
     /// # #![feature(phase)]
-    /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+    /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
     /// # fn main() {
     /// let text = "Retroactively relinquishing remunerations is reprehensible.";
     /// for pos in regex!(r"\b\w{13}\b").find_iter(text) {
@@ -263,7 +263,7 @@ impl Regex {
     ///
     /// ```rust
     /// # #![feature(phase)]
-    /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+    /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
     /// # fn main() {
     /// let re = regex!(r"'([^']+)'\s+\((\d{4})\)");
     /// let text = "Not my favorite movie: 'Citizen Kane' (1941).";
@@ -281,7 +281,7 @@ impl Regex {
     ///
     /// ```rust
     /// # #![feature(phase)]
-    /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+    /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
     /// # fn main() {
     /// let re = regex!(r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
     /// let text = "Not my favorite movie: 'Citizen Kane' (1941).";
@@ -314,7 +314,7 @@ impl Regex {
     ///
     /// ```rust
     /// # #![feature(phase)]
-    /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+    /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
     /// # fn main() {
     /// let re = regex!(r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
     /// let text = "'Citizen Kane' (1941), 'The Wizard of Oz' (1939), 'M' (1931).";
@@ -350,7 +350,7 @@ impl Regex {
     ///
     /// ```rust
     /// # #![feature(phase)]
-    /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+    /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
     /// # fn main() {
     /// let re = regex!(r"[ \t]+");
     /// let fields: Vec<&str> = re.split("a b \t  c\td    e").collect();
@@ -380,7 +380,7 @@ impl Regex {
     ///
     /// ```rust
     /// # #![feature(phase)]
-    /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+    /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
     /// # fn main() {
     /// let re = regex!(r"\W+");
     /// let fields: Vec<&str> = re.splitn("Hey! How are you?", 3).collect();
@@ -410,7 +410,7 @@ impl Regex {
     ///
     /// ```rust
     /// # #![feature(phase)]
-    /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+    /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
     /// # fn main() {
     /// let re = regex!("[^01]+");
     /// assert_eq!(re.replace("1078910", "").as_slice(), "1010");
@@ -424,7 +424,7 @@ impl Regex {
     ///
     /// ```rust
     /// # #![feature(phase)]
-    /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+    /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
     /// # use regex::Captures; fn main() {
     /// let re = regex!(r"([^,\s]+),\s+(\S+)");
     /// let result = re.replace("Springsteen, Bruce", |caps: &Captures| {
@@ -441,7 +441,7 @@ impl Regex {
     ///
     /// ```rust
     /// # #![feature(phase)]
-    /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+    /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
     /// # fn main() {
     /// let re = regex!(r"(?P<last>[^,\s]+),\s+(?P<first>\S+)");
     /// let result = re.replace("Springsteen, Bruce", "$first $last");
@@ -458,7 +458,7 @@ impl Regex {
     ///
     /// ```rust
     /// # #![feature(phase)]
-    /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+    /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
     /// # fn main() {
     /// use regex::NoExpand;
     ///
diff --git a/src/libregex/test/mod.rs b/src/libregex/test/mod.rs
index c563c84fc34..96c600b0fda 100644
--- a/src/libregex/test/mod.rs
+++ b/src/libregex/test/mod.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 #[cfg(not(stage1))]
-#[phase(syntax)]
+#[phase(plugin)]
 extern crate regex_macros;
 
 #[cfg(not(stage1))]
diff --git a/src/libregex_macros/lib.rs b/src/libregex_macros/lib.rs
index fb7e4211d49..bbee09d0f38 100644
--- a/src/libregex_macros/lib.rs
+++ b/src/libregex_macros/lib.rs
@@ -19,24 +19,24 @@
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/")]
 
-#![feature(macro_registrar, managed_boxes, quote)]
+#![feature(plugin_registrar, managed_boxes, quote)]
 
 extern crate regex;
 extern crate syntax;
+extern crate rustc;
 
 use std::rc::Rc;
 
 use syntax::ast;
 use syntax::codemap;
 use syntax::ext::build::AstBuilder;
-use syntax::ext::base::{
-    SyntaxExtension, ExtCtxt, MacResult, MacExpr, DummyResult,
-    NormalTT, BasicMacroExpander,
-};
+use syntax::ext::base::{ExtCtxt, MacResult, MacExpr, DummyResult};
 use syntax::parse;
 use syntax::parse::token;
 use syntax::print::pprust;
 
+use rustc::plugin::Registry;
+
 use regex::Regex;
 use regex::native::{
     OneChar, CharClass, Any, Save, Jump, Split,
@@ -46,11 +46,10 @@ use regex::native::{
 };
 
 /// For the `regex!` syntax extension. Do not use.
-#[macro_registrar]
+#[plugin_registrar]
 #[doc(hidden)]
-pub fn macro_registrar(register: |ast::Name, SyntaxExtension|) {
-    let expander = box BasicMacroExpander { expander: native, span: None };
-    register(token::intern("regex"), NormalTT(expander, None))
+pub fn plugin_registrar(reg: &mut Registry) {
+    reg.register_macro("regex", native);
 }
 
 /// Generates specialized code for the Pike VM for a particular regular
diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs
index 89c0a381cf9..45e9c7b562d 100644
--- a/src/librustc/driver/driver.rs
+++ b/src/librustc/driver/driver.rs
@@ -18,12 +18,14 @@ use front;
 use lib::llvm::{ContextRef, ModuleRef};
 use metadata::common::LinkMeta;
 use metadata::creader;
-use metadata::creader::Loader;
 use middle::cfg;
 use middle::cfg::graphviz::LabelledCFG;
 use middle::{trans, freevars, kind, ty, typeck, lint, reachable};
 use middle::dependency_format;
 use middle;
+use plugin::load::Plugins;
+use plugin::registry::Registry;
+use plugin;
 use util::common::time;
 use util::ppaux;
 use util::nodemap::{NodeSet};
@@ -39,7 +41,6 @@ use syntax::ast;
 use syntax::attr;
 use syntax::attr::{AttrMetaMethods};
 use syntax::crateid::CrateId;
-use syntax::ext::base::CrateLoader;
 use syntax::parse;
 use syntax::parse::token;
 use syntax::print::{pp, pprust};
@@ -75,11 +76,10 @@ pub fn compile_input(sess: Session,
                                                  output,
                                                  krate.attrs.as_slice(),
                                                  &sess);
-            let loader = &mut Loader::new(&sess);
             let id = link::find_crate_id(krate.attrs.as_slice(),
                                          outputs.out_filestem.as_slice());
             let (expanded_crate, ast_map) =
-                phase_2_configure_and_expand(&sess, loader, krate, &id);
+                phase_2_configure_and_expand(&sess, krate, &id);
             (outputs, expanded_crate, ast_map)
         };
         write_out_deps(&sess, input, &outputs, &expanded_crate);
@@ -172,7 +172,6 @@ pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input)
 /// harness if one is to be provided and injection of a dependency on the
 /// standard library and prelude.
 pub fn phase_2_configure_and_expand(sess: &Session,
-                                    loader: &mut CrateLoader,
                                     mut krate: ast::Crate,
                                     crate_id: &CrateId)
                                     -> (ast::Crate, syntax::ast_map::Map) {
@@ -197,25 +196,42 @@ pub fn phase_2_configure_and_expand(sess: &Session,
     krate = time(time_passes, "configuration 1", krate, |krate|
                  front::config::strip_unconfigured_items(krate));
 
-    krate = time(time_passes, "expansion", krate, |krate| {
-        // Windows dlls do not have rpaths, so they don't know how to find their
-        // dependencies. It's up to us to tell the system where to find all the
-        // dependent dlls. Note that this uses cfg!(windows) as opposed to
-        // targ_cfg because syntax extensions are always loaded for the host
-        // compiler, not for the target.
-        if cfg!(windows) {
-            sess.host_filesearch().add_dylib_search_paths();
+    let Plugins { macros, registrars }
+        = time(time_passes, "plugin loading", (), |_|
+               plugin::load::load_plugins(sess, &krate));
+
+    let mut registry = Registry::new(&krate);
+
+    time(time_passes, "plugin registration", (), |_| {
+        for &registrar in registrars.iter() {
+            registrar(&mut registry);
         }
-        let cfg = syntax::ext::expand::ExpansionConfig {
-            loader: loader,
-            deriving_hash_type_parameter: sess.features.default_type_params.get(),
-            crate_id: crate_id.clone(),
-        };
-        syntax::ext::expand::expand_crate(&sess.parse_sess,
-                                          cfg,
-                                          krate)
     });
 
+    let Registry { syntax_exts, .. } = registry;
+
+    krate = time(time_passes, "expansion", (krate, macros, syntax_exts),
+        |(krate, macros, syntax_exts)| {
+            // Windows dlls do not have rpaths, so they don't know how to find their
+            // dependencies. It's up to us to tell the system where to find all the
+            // dependent dlls. Note that this uses cfg!(windows) as opposed to
+            // targ_cfg because syntax extensions are always loaded for the host
+            // compiler, not for the target.
+            if cfg!(windows) {
+                sess.host_filesearch().add_dylib_search_paths();
+            }
+            let cfg = syntax::ext::expand::ExpansionConfig {
+                deriving_hash_type_parameter: sess.features.default_type_params.get(),
+                crate_id: crate_id.clone(),
+            };
+            syntax::ext::expand::expand_crate(&sess.parse_sess,
+                                              cfg,
+                                              macros,
+                                              syntax_exts,
+                                              krate)
+        }
+    );
+
     // strip again, in case expansion added anything with a #[cfg].
     krate = time(time_passes, "configuration 2", krate, |krate|
                  front::config::strip_unconfigured_items(krate));
@@ -281,9 +297,9 @@ pub fn phase_3_run_analysis_passes(sess: Session,
     time(time_passes, "looking for entry point", (),
          |_| middle::entry::find_entry_point(&sess, krate, &ast_map));
 
-    sess.macro_registrar_fn.set(
-        time(time_passes, "looking for macro registrar", (), |_|
-            syntax::ext::registrar::find_macro_registrar(
+    sess.plugin_registrar_fn.set(
+        time(time_passes, "looking for plugin registrar", (), |_|
+            plugin::build::find_plugin_registrar(
                 sess.diagnostic(), krate)));
 
     let freevars = time(time_passes, "freevar finding", (), |_|
@@ -596,9 +612,7 @@ pub fn pretty_print_input(sess: Session,
 
     let (krate, ast_map, is_expanded) = match ppm {
         PpmExpanded | PpmExpandedIdentified | PpmTyped | PpmFlowGraph(_) => {
-            let loader = &mut Loader::new(&sess);
             let (krate, ast_map) = phase_2_configure_and_expand(&sess,
-                                                                loader,
                                                                 krate,
                                                                 &id);
             (krate, Some(ast_map), true)
diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs
index 109622b6627..773b9e6e0aa 100644
--- a/src/librustc/driver/session.rs
+++ b/src/librustc/driver/session.rs
@@ -36,7 +36,7 @@ pub struct Session {
     // For a library crate, this is always none
     pub entry_fn: RefCell<Option<(NodeId, codemap::Span)>>,
     pub entry_type: Cell<Option<config::EntryFnType>>,
-    pub macro_registrar_fn: Cell<Option<ast::NodeId>>,
+    pub plugin_registrar_fn: Cell<Option<ast::NodeId>>,
     pub default_sysroot: Option<Path>,
     // The name of the root source file of the crate, in the local file system. The path is always
     // expected to be absolute. `None` means that there is no source file.
@@ -232,7 +232,7 @@ pub fn build_session_(sopts: config::Options,
         // For a library crate, this is always none
         entry_fn: RefCell::new(None),
         entry_type: Cell::new(None),
-        macro_registrar_fn: Cell::new(None),
+        plugin_registrar_fn: Cell::new(None),
         default_sysroot: default_sysroot,
         local_crate_source_file: local_crate_source_file,
         working_dir: os::getcwd(),
diff --git a/src/librustc/front/feature_gate.rs b/src/librustc/front/feature_gate.rs
index 25f0dc808c8..11dd6a86cd8 100644
--- a/src/librustc/front/feature_gate.rs
+++ b/src/librustc/front/feature_gate.rs
@@ -46,7 +46,7 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[
     ("thread_local", Active),
     ("link_args", Active),
     ("phase", Active),
-    ("macro_registrar", Active),
+    ("plugin_registrar", Active),
     ("log_syntax", Active),
     ("trace_macros", Active),
     ("concat_idents", Active),
@@ -192,10 +192,9 @@ impl<'a> Visitor<()> for Context<'a> {
             }
 
             ast::ItemFn(..) => {
-                if attr::contains_name(i.attrs.as_slice(), "macro_registrar") {
-                    self.gate_feature("macro_registrar", i.span,
-                                      "cross-crate macro exports are \
-                                       experimental and possibly buggy");
+                if attr::contains_name(i.attrs.as_slice(), "plugin_registrar") {
+                    self.gate_feature("plugin_registrar", i.span,
+                                      "compiler plugins are experimental and possibly buggy");
                 }
             }
 
diff --git a/src/librustc/front/std_inject.rs b/src/librustc/front/std_inject.rs
index fe636f7b686..0514f7de505 100644
--- a/src/librustc/front/std_inject.rs
+++ b/src/librustc/front/std_inject.rs
@@ -81,7 +81,7 @@ impl<'a> fold::Folder for StandardLibraryInjector<'a> {
                 attr::mk_attr_outer(attr::mk_attr_id(), attr::mk_list_item(
                         InternedString::new("phase"),
                         vec!(
-                            attr::mk_word_item(InternedString::new("syntax")),
+                            attr::mk_word_item(InternedString::new("plugin")),
                             attr::mk_word_item(InternedString::new("link")
                         ))))),
             vis: ast::Inherited,
diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs
index b21f3c2a019..174bcc86d26 100644
--- a/src/librustc/front/test.rs
+++ b/src/librustc/front/test.rs
@@ -16,7 +16,6 @@
 use driver::session::Session;
 use front::config;
 use front::std_inject::with_version;
-use metadata::creader::Loader;
 
 use std::cell::RefCell;
 use std::slice;
@@ -150,12 +149,10 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> {
 
 fn generate_test_harness(sess: &Session, krate: ast::Crate)
                          -> ast::Crate {
-    let loader = &mut Loader::new(sess);
     let mut cx: TestCtxt = TestCtxt {
         sess: sess,
         ext_cx: ExtCtxt::new(&sess.parse_sess, sess.opts.cfg.clone(),
                              ExpansionConfig {
-                                 loader: loader,
                                  deriving_hash_type_parameter: false,
                                  crate_id: from_str("test").unwrap(),
                              }),
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index 1b17cfb1bae..4ac4e3a5a9f 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -42,9 +42,14 @@ extern crate sync;
 extern crate syntax;
 extern crate time;
 
+#[cfg(stage0)]
 #[phase(syntax, link)]
 extern crate log;
 
+#[cfg(not(stage0))]
+#[phase(plugin, link)]
+extern crate log;
+
 pub mod middle {
     pub mod def;
     pub mod trans;
@@ -109,6 +114,8 @@ pub mod metadata;
 
 pub mod driver;
 
+pub mod plugin;
+
 pub mod util {
     pub mod common;
     pub mod ppaux;
diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs
index 6287683c1a1..2ff656853c3 100644
--- a/src/librustc/metadata/common.rs
+++ b/src/librustc/metadata/common.rs
@@ -198,7 +198,7 @@ pub static tag_native_libraries_lib: uint = 0x88;
 pub static tag_native_libraries_name: uint = 0x89;
 pub static tag_native_libraries_kind: uint = 0x8a;
 
-pub static tag_macro_registrar_fn: uint = 0x8b;
+pub static tag_plugin_registrar_fn: uint = 0x8b;
 pub static tag_exported_macros: uint = 0x8c;
 pub static tag_macro_def: uint = 0x8d;
 
diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs
index 38d2b7a67a0..4df21fbc974 100644
--- a/src/librustc/metadata/creader.rs
+++ b/src/librustc/metadata/creader.rs
@@ -21,6 +21,7 @@ use metadata::cstore::{CStore, CrateSource};
 use metadata::decoder;
 use metadata::loader;
 use metadata::loader::CratePaths;
+use plugin::load::PluginMetadata;
 
 use std::rc::Rc;
 use std::collections::HashMap;
@@ -30,7 +31,6 @@ use syntax::attr;
 use syntax::attr::AttrMetaMethods;
 use syntax::codemap::{Span};
 use syntax::diagnostic::SpanHandler;
-use syntax::ext::base::{CrateLoader, MacroCrate};
 use syntax::parse::token::InternedString;
 use syntax::parse::token;
 use syntax::crateid::CrateId;
@@ -379,23 +379,21 @@ fn resolve_crate_deps(e: &mut Env,
     }).collect()
 }
 
-pub struct Loader<'a> {
+pub struct PluginMetadataReader<'a> {
     env: Env<'a>,
 }
 
-impl<'a> Loader<'a> {
-    pub fn new(sess: &'a Session) -> Loader<'a> {
-        Loader {
+impl<'a> PluginMetadataReader<'a> {
+    pub fn new(sess: &'a Session) -> PluginMetadataReader<'a> {
+        PluginMetadataReader {
             env: Env {
                 sess: sess,
                 next_crate_num: sess.cstore.next_crate_num(),
             }
         }
     }
-}
 
-impl<'a> CrateLoader for Loader<'a> {
-    fn load_crate(&mut self, krate: &ast::ViewItem) -> MacroCrate {
+    pub fn read_plugin_metadata(&mut self, krate: &ast::ViewItem) -> PluginMetadata {
         let info = extract_crate_info(&self.env, krate).unwrap();
         let target_triple = self.env.sess.targ_cfg.target_strs.target_triple.as_slice();
         let is_cross = target_triple != driver::host_triple();
@@ -425,8 +423,8 @@ impl<'a> CrateLoader for Loader<'a> {
                 load_ctxt.os = config::cfg_os_to_meta_os(self.env.sess.targ_cfg.os);
                 load_ctxt.filesearch = self.env.sess.target_filesearch();
                 let lib = load_ctxt.load_library_crate();
-                if decoder::get_macro_registrar_fn(lib.metadata.as_slice()).is_some() {
-                    let message = format!("crate `{}` contains a macro_registrar fn but \
+                if decoder::get_plugin_registrar_fn(lib.metadata.as_slice()).is_some() {
+                    let message = format!("crate `{}` contains a plugin_registrar fn but \
                                   only a version for triple `{}` could be found (need {})",
                                   info.ident, target_triple, driver::host_triple());
                     self.env.sess.span_err(krate.span, message.as_slice());
@@ -441,10 +439,10 @@ impl<'a> CrateLoader for Loader<'a> {
             None => { load_ctxt.report_load_errs(); unreachable!() },
         };
         let macros = decoder::get_exported_macros(library.metadata.as_slice());
-        let registrar = decoder::get_macro_registrar_fn(library.metadata.as_slice()).map(|id| {
+        let registrar = decoder::get_plugin_registrar_fn(library.metadata.as_slice()).map(|id| {
             decoder::get_symbol(library.metadata.as_slice(), id).to_string()
         });
-        let mc = MacroCrate {
+        let pc = PluginMetadata {
             lib: library.dylib.clone(),
             macros: macros.move_iter().map(|x| x.to_string()).collect(),
             registrar_symbol: registrar,
@@ -454,6 +452,6 @@ impl<'a> CrateLoader for Loader<'a> {
             register_crate(&mut self.env, &None, info.ident.as_slice(),
                            &info.crate_id, krate.span, library);
         }
-        mc
+        pc
     }
 }
diff --git a/src/librustc/metadata/cstore.rs b/src/librustc/metadata/cstore.rs
index aa8d695465a..846f879104f 100644
--- a/src/librustc/metadata/cstore.rs
+++ b/src/librustc/metadata/cstore.rs
@@ -139,9 +139,6 @@ impl CStore {
             .map(|source| source.clone())
     }
 
-    pub fn dump_phase_syntax_crates(&self) {
-    }
-
     pub fn reset(&self) {
         self.metas.borrow_mut().clear();
         self.extern_mod_crate_map.borrow_mut().clear();
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index c67b5bf1a60..8a2c3c08d41 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -1255,8 +1255,8 @@ pub fn get_native_libraries(cdata: Cmd)
     return result;
 }
 
-pub fn get_macro_registrar_fn(data: &[u8]) -> Option<ast::NodeId> {
-    reader::maybe_get_doc(ebml::Doc::new(data), tag_macro_registrar_fn)
+pub fn get_plugin_registrar_fn(data: &[u8]) -> Option<ast::NodeId> {
+    reader::maybe_get_doc(ebml::Doc::new(data), tag_plugin_registrar_fn)
         .map(|doc| FromPrimitive::from_u32(reader::doc_as_u32(doc)).unwrap())
 }
 
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index 37cb75e4697..1846c9c881b 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -1582,9 +1582,9 @@ fn encode_native_libraries(ecx: &EncodeContext, ebml_w: &mut Encoder) {
     ebml_w.end_tag();
 }
 
-fn encode_macro_registrar_fn(ecx: &EncodeContext, ebml_w: &mut Encoder) {
-    match ecx.tcx.sess.macro_registrar_fn.get() {
-        Some(id) => { ebml_w.wr_tagged_u32(tag_macro_registrar_fn, id); }
+fn encode_plugin_registrar_fn(ecx: &EncodeContext, ebml_w: &mut Encoder) {
+    match ecx.tcx.sess.plugin_registrar_fn.get() {
+        Some(id) => { ebml_w.wr_tagged_u32(tag_plugin_registrar_fn, id); }
         None => {}
     }
 }
@@ -1791,7 +1791,7 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate)
         dep_bytes: u64,
         lang_item_bytes: u64,
         native_lib_bytes: u64,
-        macro_registrar_fn_bytes: u64,
+        plugin_registrar_fn_bytes: u64,
         macro_defs_bytes: u64,
         impl_bytes: u64,
         misc_bytes: u64,
@@ -1805,7 +1805,7 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate)
         dep_bytes: 0,
         lang_item_bytes: 0,
         native_lib_bytes: 0,
-        macro_registrar_fn_bytes: 0,
+        plugin_registrar_fn_bytes: 0,
         macro_defs_bytes: 0,
         impl_bytes: 0,
         misc_bytes: 0,
@@ -1870,10 +1870,10 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate)
     encode_native_libraries(&ecx, &mut ebml_w);
     stats.native_lib_bytes = ebml_w.writer.tell().unwrap() - i;
 
-    // Encode the macro registrar function
+    // Encode the plugin registrar function
     i = ebml_w.writer.tell().unwrap();
-    encode_macro_registrar_fn(&ecx, &mut ebml_w);
-    stats.macro_registrar_fn_bytes = ebml_w.writer.tell().unwrap() - i;
+    encode_plugin_registrar_fn(&ecx, &mut ebml_w);
+    stats.plugin_registrar_fn_bytes = ebml_w.writer.tell().unwrap() - i;
 
     // Encode macro definitions
     i = ebml_w.writer.tell().unwrap();
@@ -1912,18 +1912,18 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate)
         }
 
         println!("metadata stats:");
-        println!("      attribute bytes: {}", stats.attr_bytes);
-        println!("            dep bytes: {}", stats.dep_bytes);
-        println!("      lang item bytes: {}", stats.lang_item_bytes);
-        println!("         native bytes: {}", stats.native_lib_bytes);
-        println!("macro registrar bytes: {}", stats.macro_registrar_fn_bytes);
-        println!("      macro def bytes: {}", stats.macro_defs_bytes);
-        println!("           impl bytes: {}", stats.impl_bytes);
-        println!("           misc bytes: {}", stats.misc_bytes);
-        println!("           item bytes: {}", stats.item_bytes);
-        println!("          index bytes: {}", stats.index_bytes);
-        println!("           zero bytes: {}", stats.zero_bytes);
-        println!("          total bytes: {}", stats.total_bytes);
+        println!("       attribute bytes: {}", stats.attr_bytes);
+        println!("             dep bytes: {}", stats.dep_bytes);
+        println!("       lang item bytes: {}", stats.lang_item_bytes);
+        println!("          native bytes: {}", stats.native_lib_bytes);
+        println!("plugin registrar bytes: {}", stats.plugin_registrar_fn_bytes);
+        println!("       macro def bytes: {}", stats.macro_defs_bytes);
+        println!("            impl bytes: {}", stats.impl_bytes);
+        println!("            misc bytes: {}", stats.misc_bytes);
+        println!("            item bytes: {}", stats.item_bytes);
+        println!("           index bytes: {}", stats.index_bytes);
+        println!("            zero bytes: {}", stats.zero_bytes);
+        println!("           total bytes: {}", stats.total_bytes);
     }
 }
 
diff --git a/src/libsyntax/ext/registrar.rs b/src/librustc/plugin/build.rs
index b76708147e1..ad35c4efe11 100644
--- a/src/libsyntax/ext/registrar.rs
+++ b/src/librustc/plugin/build.rs
@@ -8,23 +8,25 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use ast;
-use attr;
-use codemap::Span;
-use diagnostic;
-use visit;
-use visit::Visitor;
+//! Used by `rustc` when compiling a plugin crate.
 
-struct MacroRegistrarContext {
+use syntax::ast;
+use syntax::attr;
+use syntax::codemap::Span;
+use syntax::diagnostic;
+use syntax::visit;
+use syntax::visit::Visitor;
+
+struct RegistrarFinder {
     registrars: Vec<(ast::NodeId, Span)> ,
 }
 
-impl Visitor<()> for MacroRegistrarContext {
+impl Visitor<()> for RegistrarFinder {
     fn visit_item(&mut self, item: &ast::Item, _: ()) {
         match item.node {
             ast::ItemFn(..) => {
                 if attr::contains_name(item.attrs.as_slice(),
-                                       "macro_registrar") {
+                                       "plugin_registrar") {
                     self.registrars.push((item.id, item.span));
                 }
             }
@@ -35,20 +37,21 @@ impl Visitor<()> for MacroRegistrarContext {
     }
 }
 
-pub fn find_macro_registrar(diagnostic: &diagnostic::SpanHandler,
-                            krate: &ast::Crate) -> Option<ast::NodeId> {
-    let mut ctx = MacroRegistrarContext { registrars: Vec::new() };
-    visit::walk_crate(&mut ctx, krate, ());
+/// Find the function marked with `#[plugin_registrar]`, if any.
+pub fn find_plugin_registrar(diagnostic: &diagnostic::SpanHandler,
+                             krate: &ast::Crate) -> Option<ast::NodeId> {
+    let mut finder = RegistrarFinder { registrars: Vec::new() };
+    visit::walk_crate(&mut finder, krate, ());
 
-    match ctx.registrars.len() {
+    match finder.registrars.len() {
         0 => None,
         1 => {
-            let (node_id, _) = ctx.registrars.pop().unwrap();
+            let (node_id, _) = finder.registrars.pop().unwrap();
             Some(node_id)
         },
         _ => {
-            diagnostic.handler().err("multiple macro registration functions found");
-            for &(_, span) in ctx.registrars.iter() {
+            diagnostic.handler().err("multiple plugin registration functions found");
+            for &(_, span) in finder.registrars.iter() {
                 diagnostic.span_note(span, "one is here");
             }
             diagnostic.handler().abort_if_errors();
diff --git a/src/librustc/plugin/load.rs b/src/librustc/plugin/load.rs
new file mode 100644
index 00000000000..ba50a15a82b
--- /dev/null
+++ b/src/librustc/plugin/load.rs
@@ -0,0 +1,145 @@
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Used by `rustc` when loading a plugin.
+
+use driver::session::Session;
+use metadata::creader::PluginMetadataReader;
+use plugin::registry::Registry;
+
+use std::mem;
+use std::os;
+use std::unstable::dynamic_lib::DynamicLibrary;
+use syntax::ast;
+use syntax::attr;
+use syntax::visit;
+use syntax::visit::Visitor;
+use syntax::ext::expand::ExportedMacros;
+use syntax::attr::AttrMetaMethods;
+
+/// Plugin-related crate metadata.
+pub struct PluginMetadata {
+    /// Source code of macros exported by the crate.
+    pub macros: Vec<String>,
+    /// Path to the shared library file.
+    pub lib: Option<Path>,
+    /// Symbol name of the plugin registrar function.
+    pub registrar_symbol: Option<String>,
+}
+
+/// Pointer to a registrar function.
+pub type PluginRegistrarFun =
+    fn(&mut Registry);
+
+/// Information about loaded plugins.
+pub struct Plugins {
+    /// Source code of exported macros.
+    pub macros: Vec<ExportedMacros>,
+    /// Registrars, as function pointers.
+    pub registrars: Vec<PluginRegistrarFun>,
+}
+
+struct PluginLoader<'a> {
+    sess: &'a Session,
+    reader: PluginMetadataReader<'a>,
+    plugins: Plugins,
+}
+
+impl<'a> PluginLoader<'a> {
+    fn new(sess: &'a Session) -> PluginLoader<'a> {
+        PluginLoader {
+            sess: sess,
+            reader: PluginMetadataReader::new(sess),
+            plugins: Plugins {
+                macros: vec!(),
+                registrars: vec!(),
+            },
+        }
+    }
+}
+
+/// Read plugin metadata and dynamically load registrar functions.
+pub fn load_plugins(sess: &Session, krate: &ast::Crate) -> Plugins {
+    let mut loader = PluginLoader::new(sess);
+    visit::walk_crate(&mut loader, krate, ());
+    loader.plugins
+}
+
+impl<'a> Visitor<()> for PluginLoader<'a> {
+    fn visit_view_item(&mut self, vi: &ast::ViewItem, _: ()) {
+        match vi.node {
+            ast::ViewItemExternCrate(name, _, _) => {
+                let mut plugin_phase = false;
+
+                for attr in vi.attrs.iter().filter(|a| a.check_name("phase")) {
+                    let phases = attr.meta_item_list().unwrap_or(&[]);
+                    if attr::contains_name(phases, "plugin") {
+                        plugin_phase = true;
+                    }
+                    if attr::contains_name(phases, "syntax") {
+                        plugin_phase = true;
+                        self.sess.span_warn(attr.span,
+                            "phase(syntax) is a deprecated synonym for phase(plugin)");
+                    }
+                }
+
+                if !plugin_phase { return; }
+
+                let PluginMetadata { macros, lib, registrar_symbol } =
+                    self.reader.read_plugin_metadata(vi);
+
+                self.plugins.macros.push(ExportedMacros {
+                    crate_name: name,
+                    macros: macros,
+                });
+
+                match (lib, registrar_symbol) {
+                    (Some(lib), Some(symbol))
+                        => self.dylink_registrar(vi, lib, symbol),
+                    _ => (),
+                }
+            }
+            _ => (),
+        }
+    }
+}
+
+impl<'a> PluginLoader<'a> {
+    // Dynamically link a registrar function into the compiler process.
+    fn dylink_registrar(&mut self, vi: &ast::ViewItem, path: Path, symbol: String) {
+        // Make sure the path contains a / or the linker will search for it.
+        let path = os::make_absolute(&path);
+
+        let lib = match DynamicLibrary::open(Some(&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) => self.sess.span_fatal(vi.span, err.as_slice())
+        };
+
+        unsafe {
+            let registrar: PluginRegistrarFun =
+                match lib.symbol(symbol.as_slice()) {
+                    Ok(registrar) => registrar,
+                    // again fatal if we can't register macros
+                    Err(err) => self.sess.span_fatal(vi.span, err.as_slice())
+                };
+
+            self.plugins.registrars.push(registrar);
+
+            // 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 task).
+            mem::forget(lib);
+
+        }
+    }
+}
diff --git a/src/librustc/plugin/mod.rs b/src/librustc/plugin/mod.rs
new file mode 100644
index 00000000000..fa70ffc7392
--- /dev/null
+++ b/src/librustc/plugin/mod.rs
@@ -0,0 +1,64 @@
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+ * Infrastructure for compiler plugins.
+ *
+ * Plugins are Rust libraries which extend the behavior of `rustc`
+ * in various ways.
+ *
+ * Plugin authors will use the `Registry` type re-exported by
+ * this module, along with its methods.  The rest of the module
+ * is for use by `rustc` itself.
+ *
+ * To define a plugin, build a dylib crate with a
+ * `#[plugin_registrar]` function:
+ *
+ * ```rust,ignore
+ * #![crate_id = "myplugin"]
+ * #![crate_type = "dylib"]
+ * #![feature(plugin_registrar)]
+ *
+ * extern crate rustc;
+ *
+ * use rustc::plugin::Registry;
+ *
+ * #[plugin_registrar]
+ * pub fn plugin_registrar(reg: &mut Registry) {
+ *     reg.register_macro("mymacro", expand_mymacro);
+ * }
+ *
+ * fn expand_mymacro(...) {  // details elided
+ * ```
+ *
+ * WARNING: We currently don't check that the registrar function
+ * has the appropriate type!
+ *
+ * To use a plugin while compiling another crate:
+ *
+ * ```rust
+ * #![feature(phase)]
+ *
+ * #[phase(plugin)]
+ * extern crate myplugin;
+ * ```
+ *
+ * If you also need the plugin crate available at runtime, use
+ * `phase(plugin, link)`.
+ *
+ * See `src/test/auxiliary/macro_crate_test.rs` and `src/libfourcc`
+ * for examples of syntax extension plugins.
+ */
+
+pub use self::registry::Registry;
+
+pub mod registry;
+pub mod load;
+pub mod build;
diff --git a/src/librustc/plugin/registry.rs b/src/librustc/plugin/registry.rs
new file mode 100644
index 00000000000..f6e37822325
--- /dev/null
+++ b/src/librustc/plugin/registry.rs
@@ -0,0 +1,70 @@
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Used by plugin crates to tell `rustc` about the plugins they provide.
+
+use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT};
+use syntax::ext::base::{IdentTT, ItemDecorator, ItemModifier, BasicMacroExpander};
+use syntax::ext::base::{MacroExpanderFn};
+use syntax::codemap::Span;
+use syntax::parse::token;
+use syntax::ast;
+
+/// Structure used to register plugins.
+///
+/// A plugin registrar function takes an `&mut Registry` and should call
+/// methods to register its plugins.
+///
+/// This struct has public fields and other methods for use by `rustc`
+/// itself. They are not documented here, and plugin authors should
+/// not use them.
+pub struct Registry {
+    #[doc(hidden)]
+    pub krate_span: Span,
+
+    #[doc(hidden)]
+    pub syntax_exts: Vec<NamedSyntaxExtension>,
+}
+
+impl Registry {
+    #[doc(hidden)]
+    pub fn new(krate: &ast::Crate) -> Registry {
+        Registry {
+            krate_span: krate.span,
+            syntax_exts: vec!(),
+        }
+    }
+
+    /// Register a syntax extension of any kind.
+    ///
+    /// This is the most general hook into `libsyntax`'s expansion behavior.
+    pub fn register_syntax_extension(&mut self, name: ast::Name, extension: SyntaxExtension) {
+        self.syntax_exts.push((name, match extension {
+            NormalTT(ext, _) => NormalTT(ext, Some(self.krate_span)),
+            IdentTT(ext, _) => IdentTT(ext, Some(self.krate_span)),
+            ItemDecorator(ext) => ItemDecorator(ext),
+            ItemModifier(ext) => ItemModifier(ext),
+        }));
+    }
+
+    /// Register a macro of the usual kind.
+    ///
+    /// This is a convenience wrapper for `register_syntax_extension`.
+    /// It builds for you a `NormalTT` with a `BasicMacroExpander`,
+    /// and also takes care of interning the macro's name.
+    pub fn register_macro(&mut self, name: &str, expander: MacroExpanderFn) {
+        self.register_syntax_extension(
+            token::intern(name),
+            NormalTT(box BasicMacroExpander {
+                expander: expander,
+                span: None,
+            }, None));
+    }
+}
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 1786e5b3fd2..f848c5224b7 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -10,7 +10,6 @@
 
 use rustc;
 use rustc::{driver, middle};
-use rustc::metadata::creader::Loader;
 use rustc::middle::privacy;
 use rustc::middle::lint;
 
@@ -100,8 +99,8 @@ fn get_ast_and_resolve(cpath: &Path, libs: HashSet<Path>, cfgs: Vec<String>)
     }
 
     let krate = phase_1_parse_input(&sess, cfg, &input);
-    let (krate, ast_map) = phase_2_configure_and_expand(&sess, &mut Loader::new(&sess),
-                                                        krate, &from_str("rustdoc").unwrap());
+    let (krate, ast_map) = phase_2_configure_and_expand(&sess, krate,
+                                                        &from_str("rustdoc").unwrap());
     let driver::driver::CrateAnalysis {
         exported_items, public_items, ty_cx, ..
     } = phase_3_run_analysis_passes(sess, &krate, ast_map);
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index e623d54675c..05875f59fbe 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -19,8 +19,6 @@
 extern crate debug;
 extern crate getopts;
 extern crate libc;
-#[phase(syntax, link)]
-extern crate log;
 extern crate rustc;
 extern crate serialize;
 extern crate sync;
@@ -28,6 +26,14 @@ extern crate syntax;
 extern crate testing = "test";
 extern crate time;
 
+#[cfg(stage0)]
+#[phase(syntax, link)]
+extern crate log;
+
+#[cfg(not(stage0))]
+#[phase(plugin, link)]
+extern crate log;
+
 use std::io;
 use std::io::{File, MemWriter};
 use std::str;
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 745e29508d2..34363058297 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -23,7 +23,6 @@ use rustc::back::link;
 use rustc::driver::config;
 use rustc::driver::driver;
 use rustc::driver::session;
-use rustc::metadata::creader::Loader;
 use syntax::ast;
 use syntax::codemap::{CodeMap, dummy_spanned};
 use syntax::diagnostic;
@@ -68,7 +67,7 @@ pub fn run(input: &str,
         @dummy_spanned(ast::MetaWord(cfg_))
     }));
     let krate = driver::phase_1_parse_input(&sess, cfg, &input);
-    let (krate, _) = driver::phase_2_configure_and_expand(&sess, &mut Loader::new(&sess), krate,
+    let (krate, _) = driver::phase_2_configure_and_expand(&sess, krate,
                                                           &from_str("rustdoc-test").unwrap());
 
     let ctx = @core::DocContext {
diff --git a/src/librustrt/lib.rs b/src/librustrt/lib.rs
index 3158687c6ab..bb57f5c038c 100644
--- a/src/librustrt/lib.rs
+++ b/src/librustrt/lib.rs
@@ -19,8 +19,14 @@
 #![no_std]
 #![experimental]
 
+#[cfg(stage0)]
 #[phase(syntax, link)]
 extern crate core;
+
+#[cfg(not(stage0))]
+#[phase(plugin, link)]
+extern crate core;
+
 extern crate alloc;
 extern crate libc;
 extern crate collections;
@@ -28,7 +34,9 @@ extern crate collections;
 #[cfg(test)] extern crate realrustrt = "rustrt";
 #[cfg(test)] extern crate test;
 #[cfg(test)] extern crate native;
-#[cfg(test)] #[phase(syntax, link)] extern crate std;
+
+#[cfg(test, stage0)] #[phase(syntax, link)] extern crate std;
+#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate std;
 
 pub use self::util::{Stdio, Stdout, Stderr};
 pub use self::unwind::{begin_unwind, begin_unwind_fmt};
diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs
index 08348c96333..33d20ed7bcd 100644
--- a/src/libserialize/lib.rs
+++ b/src/libserialize/lib.rs
@@ -27,9 +27,15 @@ Core encoding and decoding interfaces.
 // test harness access
 #[cfg(test)]
 extern crate test;
+
+#[cfg(stage0)]
 #[phase(syntax, link)]
 extern crate log;
 
+#[cfg(not(stage0))]
+#[phase(plugin, link)]
+extern crate log;
+
 pub use self::serialize::{Decoder, Encoder, Decodable, Encodable,
                           DecoderHelpers, EncoderHelpers};
 
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index fbdbc13e1b4..85813c02d55 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -119,7 +119,8 @@
 #[cfg(test)] extern crate native;
 #[cfg(test)] extern crate green;
 #[cfg(test)] extern crate debug;
-#[cfg(test)] #[phase(syntax, link)] extern crate log;
+#[cfg(test, stage0)] #[phase(syntax, link)] extern crate log;
+#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate log;
 
 extern crate alloc;
 extern crate core;
diff --git a/src/libsync/lib.rs b/src/libsync/lib.rs
index fc4d5fec5f5..44d17e6fb95 100644
--- a/src/libsync/lib.rs
+++ b/src/libsync/lib.rs
@@ -25,9 +25,12 @@
 
 #![deny(missing_doc)]
 
-#[cfg(test)]
+#[cfg(test, stage0)]
 #[phase(syntax, link)] extern crate log;
 
+#[cfg(test, not(stage0))]
+#[phase(plugin, link)] extern crate log;
+
 extern crate alloc;
 
 pub use comm::{DuplexStream, duplex};
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 521b7ee0063..e81421cff04 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -95,9 +95,6 @@ impl IdentMacroExpander for BasicIdentMacroExpander {
 pub type IdentMacroExpanderFn =
     fn(&mut ExtCtxt, Span, ast::Ident, Vec<ast::TokenTree>) -> Box<MacResult>;
 
-pub type MacroCrateRegistrationFun =
-    fn(|ast::Name, SyntaxExtension|);
-
 /// The result of a macro expansion. The return values of the various
 /// methods are spliced into the AST at the callsite of the macro (or
 /// just into the compiler's internal macro table, for `make_def`).
@@ -268,6 +265,8 @@ pub enum SyntaxExtension {
     IdentTT(Box<IdentMacroExpander:'static>, Option<Span>),
 }
 
+pub type NamedSyntaxExtension = (Name, SyntaxExtension);
+
 pub struct BlockInfo {
     // should macros escape from this scope?
     pub macros_escape: bool,
@@ -392,16 +391,6 @@ pub fn syntax_expander_table() -> SyntaxEnv {
     syntax_expanders
 }
 
-pub struct MacroCrate {
-    pub lib: Option<Path>,
-    pub macros: Vec<String>,
-    pub registrar_symbol: Option<String>,
-}
-
-pub trait CrateLoader {
-    fn load_crate(&mut self, krate: &ast::ViewItem) -> MacroCrate;
-}
-
 // One of these is made during expansion and incrementally updated as we go;
 // when a macro expansion occurs, the resulting nodes have the backtrace()
 // -> expn_info of their expansion context stored into their span.
@@ -409,7 +398,7 @@ pub struct ExtCtxt<'a> {
     pub parse_sess: &'a parse::ParseSess,
     pub cfg: ast::CrateConfig,
     pub backtrace: Option<@ExpnInfo>,
-    pub ecfg: expand::ExpansionConfig<'a>,
+    pub ecfg: expand::ExpansionConfig,
 
     pub mod_path: Vec<ast::Ident> ,
     pub trace_mac: bool,
@@ -417,7 +406,7 @@ pub struct ExtCtxt<'a> {
 
 impl<'a> ExtCtxt<'a> {
     pub fn new<'a>(parse_sess: &'a parse::ParseSess, cfg: ast::CrateConfig,
-                   ecfg: expand::ExpansionConfig<'a>) -> ExtCtxt<'a> {
+                   ecfg: expand::ExpansionConfig) -> ExtCtxt<'a> {
         ExtCtxt {
             parse_sess: parse_sess,
             cfg: cfg,
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 03001acc5d0..bb335e7bed0 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -29,10 +29,6 @@ use visit;
 use visit::Visitor;
 use util::small_vector::SmallVector;
 
-use std::mem;
-use std::os;
-use std::unstable::dynamic_lib::DynamicLibrary;
-
 pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr {
     match e.node {
         // expr_mac should really be expr_ext or something; it's the
@@ -497,96 +493,6 @@ pub fn expand_item_mac(it: @ast::Item, fld: &mut MacroExpander)
     return items;
 }
 
-// load macros from syntax-phase crates
-pub fn expand_view_item(vi: &ast::ViewItem,
-                        fld: &mut MacroExpander)
-                        -> ast::ViewItem {
-    match vi.node {
-        ast::ViewItemExternCrate(..) => {
-            let should_load = vi.attrs.iter().any(|attr| {
-                attr.check_name("phase") &&
-                    attr.meta_item_list().map_or(false, |phases| {
-                        attr::contains_name(phases, "syntax")
-                    })
-            });
-
-            if should_load {
-                load_extern_macros(vi, fld);
-            }
-        }
-        ast::ViewItemUse(_) => {}
-    }
-
-    noop_fold_view_item(vi, fld)
-}
-
-fn load_extern_macros(krate: &ast::ViewItem, fld: &mut MacroExpander) {
-    let MacroCrate { lib, macros, registrar_symbol } =
-        fld.cx.ecfg.loader.load_crate(krate);
-
-    let crate_name = match krate.node {
-        ast::ViewItemExternCrate(name, _, _) => name,
-        _ => unreachable!()
-    };
-    let name = format!("<{} macros>", token::get_ident(crate_name));
-    let name = name.to_string();
-
-    for source in macros.iter() {
-        let item = parse::parse_item_from_source_str(name.clone(),
-                                                     (*source).clone(),
-                                                     fld.cx.cfg(),
-                                                     fld.cx.parse_sess())
-                .expect("expected a serialized item");
-        expand_item_mac(item, fld);
-    }
-
-    let path = match lib {
-        Some(path) => path,
-        None => return
-    };
-    // Make sure the path contains a / or the linker will search for it.
-    let path = os::make_absolute(&path);
-
-    let registrar = match registrar_symbol {
-        Some(registrar) => registrar,
-        None => return
-    };
-
-    debug!("load_extern_macros: mapped crate {} to path {} and registrar {:s}",
-           crate_name, path.display(), registrar);
-
-    let lib = match DynamicLibrary::open(Some(&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) => fld.cx.span_fatal(krate.span, err.as_slice())
-    };
-
-    unsafe {
-        let registrar: MacroCrateRegistrationFun =
-            match lib.symbol(registrar.as_slice()) {
-                Ok(registrar) => registrar,
-                // again fatal if we can't register macros
-                Err(err) => fld.cx.span_fatal(krate.span, err.as_slice())
-            };
-        registrar(|name, extension| {
-            let extension = match extension {
-                NormalTT(ext, _) => NormalTT(ext, Some(krate.span)),
-                IdentTT(ext, _) => IdentTT(ext, Some(krate.span)),
-                ItemDecorator(ext) => ItemDecorator(ext),
-                ItemModifier(ext) => ItemModifier(ext),
-            };
-            fld.extsbox.insert(name, extension);
-        });
-
-        // Intentionally leak the dynamic library. We can't ever unload it
-        // since the library can do things that will outlive the expansion
-        // phase (e.g. make an @-box cycle or launch a task).
-        mem::forget(lib);
-    }
-}
-
 // expand a stmt
 pub fn expand_stmt(s: &Stmt, fld: &mut MacroExpander) -> SmallVector<@Stmt> {
     // why the copying here and not in expand_expr?
@@ -969,10 +875,6 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
         expand_item(item, self)
     }
 
-    fn fold_view_item(&mut self, vi: &ast::ViewItem) -> ast::ViewItem {
-        expand_view_item(vi, self)
-    }
-
     fn fold_stmt(&mut self, stmt: &ast::Stmt) -> SmallVector<@ast::Stmt> {
         expand_stmt(stmt, self)
     }
@@ -986,14 +888,20 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
     }
 }
 
-pub struct ExpansionConfig<'a> {
-    pub loader: &'a mut CrateLoader,
+pub struct ExpansionConfig {
     pub deriving_hash_type_parameter: bool,
     pub crate_id: CrateId,
 }
 
+pub struct ExportedMacros {
+    pub crate_name: Ident,
+    pub macros: Vec<String>,
+}
+
 pub fn expand_crate(parse_sess: &parse::ParseSess,
                     cfg: ExpansionConfig,
+                    macros: Vec<ExportedMacros>,
+                    user_exts: Vec<NamedSyntaxExtension>,
                     c: Crate) -> Crate {
     let mut cx = ExtCtxt::new(parse_sess, c.config.clone(), cfg);
     let mut expander = MacroExpander {
@@ -1001,6 +909,24 @@ pub fn expand_crate(parse_sess: &parse::ParseSess,
         cx: &mut cx,
     };
 
+    for ExportedMacros { crate_name, macros } in macros.move_iter() {
+        let name = format!("<{} macros>", token::get_ident(crate_name))
+            .into_string();
+
+        for source in macros.move_iter() {
+            let item = parse::parse_item_from_source_str(name.clone(),
+                                                         source,
+                                                         expander.cx.cfg(),
+                                                         expander.cx.parse_sess())
+                    .expect("expected a serialized item");
+            expand_item_mac(item, &mut expander);
+        }
+    }
+
+    for (name, extension) in user_exts.move_iter() {
+        expander.extsbox.insert(name, extension);
+    }
+
     let ret = expander.fold_crate(c);
     parse_sess.span_diagnostic.handler().abort_if_errors();
     return ret;
@@ -1093,7 +1019,6 @@ mod test {
     use attr;
     use codemap;
     use codemap::Spanned;
-    use ext::base::{CrateLoader, MacroCrate};
     use ext::mtwt;
     use parse;
     use parse::token;
@@ -1137,14 +1062,6 @@ mod test {
         }
     }
 
-    struct ErrLoader;
-
-    impl CrateLoader for ErrLoader {
-        fn load_crate(&mut self, _: &ast::ViewItem) -> MacroCrate {
-            fail!("lolwut")
-        }
-    }
-
     // these following tests are quite fragile, in that they don't test what
     // *kind* of failure occurs.
 
@@ -1159,13 +1076,11 @@ mod test {
             src,
             Vec::new(), &sess);
         // should fail:
-        let mut loader = ErrLoader;
         let cfg = ::syntax::ext::expand::ExpansionConfig {
-            loader: &mut loader,
             deriving_hash_type_parameter: false,
             crate_id: from_str("test").unwrap(),
         };
-        expand_crate(&sess,cfg,crate_ast);
+        expand_crate(&sess,cfg,vec!(),vec!(),crate_ast);
     }
 
     // make sure that macros can leave scope for modules
@@ -1178,14 +1093,11 @@ mod test {
             "<test>".to_string(),
             src,
             Vec::new(), &sess);
-        // should fail:
-        let mut loader = ErrLoader;
         let cfg = ::syntax::ext::expand::ExpansionConfig {
-            loader: &mut loader,
             deriving_hash_type_parameter: false,
             crate_id: from_str("test").unwrap(),
         };
-        expand_crate(&sess,cfg,crate_ast);
+        expand_crate(&sess,cfg,vec!(),vec!(),crate_ast);
     }
 
     // macro_escape modules shouldn't cause macros to leave scope
@@ -1198,13 +1110,11 @@ mod test {
             src,
             Vec::new(), &sess);
         // should fail:
-        let mut loader = ErrLoader;
         let cfg = ::syntax::ext::expand::ExpansionConfig {
-            loader: &mut loader,
             deriving_hash_type_parameter: false,
             crate_id: from_str("test").unwrap(),
         };
-        expand_crate(&sess, cfg, crate_ast);
+        expand_crate(&sess, cfg, vec!(), vec!(), crate_ast);
     }
 
     #[test] fn test_contains_flatten (){
@@ -1237,13 +1147,11 @@ mod test {
         let ps = parse::new_parse_sess();
         let crate_ast = string_to_parser(&ps, crate_str).parse_crate_mod();
         // the cfg argument actually does matter, here...
-        let mut loader = ErrLoader;
         let cfg = ::syntax::ext::expand::ExpansionConfig {
-            loader: &mut loader,
             deriving_hash_type_parameter: false,
             crate_id: from_str("test").unwrap(),
         };
-        expand_crate(&ps,cfg,crate_ast)
+        expand_crate(&ps,cfg,vec!(),vec!(),crate_ast)
     }
 
     //fn expand_and_resolve(crate_str: @str) -> ast::crate {
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 1ab420eb69b..754518f5fea 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -32,8 +32,15 @@ This API is completely unstable and subject to change.
 
 extern crate serialize;
 extern crate term;
+
+#[cfg(stage0)]
 #[phase(syntax, link)]
 extern crate log;
+
+#[cfg(not(stage0))]
+#[phase(plugin, link)]
+extern crate log;
+
 extern crate fmt_macros;
 extern crate debug;
 
@@ -74,7 +81,6 @@ pub mod ext {
     pub mod asm;
     pub mod base;
     pub mod expand;
-    pub mod registrar;
 
     pub mod quote;
 
diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs
index cc813262576..76118f642ab 100644
--- a/src/libterm/lib.rs
+++ b/src/libterm/lib.rs
@@ -52,7 +52,8 @@
 
 #![deny(missing_doc)]
 
-#[phase(syntax, link)] extern crate log;
+#[cfg(stage0)] #[phase(syntax, link)] extern crate log;
+#[cfg(not(stage0))] #[phase(plugin, link)] extern crate log;
 
 pub use terminfo::TerminfoTerminal;
 #[cfg(windows)]
diff --git a/src/libtime/lib.rs b/src/libtime/lib.rs
index f087b9289c3..f2af5943335 100644
--- a/src/libtime/lib.rs
+++ b/src/libtime/lib.rs
@@ -23,7 +23,9 @@
 #![deny(deprecated_owned_vector)]
 
 #[cfg(test)] extern crate debug;
-#[cfg(test)] #[phase(syntax, link)] extern crate log;
+
+#[cfg(test, stage0)] #[phase(syntax, link)] extern crate log;
+#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate log;
 
 extern crate serialize;
 extern crate libc;
diff --git a/src/test/auxiliary/issue-13560-3.rs b/src/test/auxiliary/issue-13560-3.rs
index 3b77b244ce8..dfd13851774 100644
--- a/src/test/auxiliary/issue-13560-3.rs
+++ b/src/test/auxiliary/issue-13560-3.rs
@@ -13,6 +13,6 @@
 #![crate_type = "rlib"]
 #![feature(phase)]
 
-#[phase(syntax)] extern crate t1 = "issue-13560-1";
-#[phase(syntax, link)] extern crate t2 = "issue-13560-2";
+#[phase(plugin)] extern crate t1 = "issue-13560-1";
+#[phase(plugin, link)] extern crate t2 = "issue-13560-2";
 
diff --git a/src/test/auxiliary/logging_right_crate.rs b/src/test/auxiliary/logging_right_crate.rs
index 3f0da3e344a..0c4af97b410 100644
--- a/src/test/auxiliary/logging_right_crate.rs
+++ b/src/test/auxiliary/logging_right_crate.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 #![feature(phase)]
-#[phase(syntax, link)] extern crate log;
+#[phase(plugin, link)] extern crate log;
 extern crate debug;
 
 pub fn foo<T>() {
diff --git a/src/test/auxiliary/macro_crate_test.rs b/src/test/auxiliary/macro_crate_test.rs
index 95f2a8c1ca1..805b8a894cb 100644
--- a/src/test/auxiliary/macro_crate_test.rs
+++ b/src/test/auxiliary/macro_crate_test.rs
@@ -10,29 +10,28 @@
 
 // force-host
 
-#![feature(globs, macro_registrar, macro_rules, quote, managed_boxes)]
+#![feature(globs, plugin_registrar, macro_rules, quote, managed_boxes)]
 
 extern crate syntax;
+extern crate rustc;
 
-use syntax::ast::{Name, TokenTree, Item, MetaItem};
+use syntax::ast::{TokenTree, Item, MetaItem};
 use syntax::codemap::Span;
 use syntax::ext::base::*;
 use syntax::parse::token;
+use rustc::plugin::Registry;
 
 #[macro_export]
 macro_rules! exported_macro (() => (2))
 
 macro_rules! unexported_macro (() => (3))
 
-#[macro_registrar]
-pub fn macro_registrar(register: |Name, SyntaxExtension|) {
-    register(token::intern("make_a_1"),
-        NormalTT(box BasicMacroExpander {
-            expander: expand_make_a_1,
-            span: None,
-        },
-        None));
-    register(token::intern("into_foo"), ItemModifier(expand_into_foo));
+#[plugin_registrar]
+pub fn plugin_registrar(reg: &mut Registry) {
+    reg.register_macro("make_a_1", expand_make_a_1);
+    reg.register_syntax_extension(
+        token::intern("into_foo"),
+        ItemModifier(expand_into_foo));
 }
 
 fn expand_make_a_1(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
diff --git a/src/test/auxiliary/macro_crate_outlive_expansion_phase.rs b/src/test/auxiliary/plugin_crate_outlive_expansion_phase.rs
index 670673fe047..213fdd6b74a 100644
--- a/src/test/auxiliary/macro_crate_outlive_expansion_phase.rs
+++ b/src/test/auxiliary/plugin_crate_outlive_expansion_phase.rs
@@ -10,13 +10,12 @@
 
 // force-host
 
-#![feature(macro_registrar)]
+#![feature(plugin_registrar)]
 
-extern crate syntax;
+extern crate rustc;
 
 use std::any::Any;
-use syntax::ast::Name;
-use syntax::ext::base::SyntaxExtension;
+use rustc::plugin::Registry;
 
 struct Foo {
     foo: int
@@ -26,8 +25,8 @@ impl Drop for Foo {
     fn drop(&mut self) {}
 }
 
-#[macro_registrar]
-pub fn registrar(_: |Name, SyntaxExtension|) {
+#[plugin_registrar]
+pub fn registrar(_: &mut Registry) {
     local_data_key!(foo: Box<Any:Send>);
     foo.replace(Some(box Foo { foo: 10 } as Box<Any:Send>));
 }
diff --git a/src/test/auxiliary/syntax-extension-with-dll-deps-2.rs b/src/test/auxiliary/syntax-extension-with-dll-deps-2.rs
index 93b56a7600d..04318fcae27 100644
--- a/src/test/auxiliary/syntax-extension-with-dll-deps-2.rs
+++ b/src/test/auxiliary/syntax-extension-with-dll-deps-2.rs
@@ -12,24 +12,20 @@
 // no-prefer-dynamic
 
 #![crate_type = "dylib"]
-#![feature(macro_registrar, quote, globs)]
+#![feature(plugin_registrar, quote, globs)]
 
 extern crate other = "syntax-extension-with-dll-deps-1";
 extern crate syntax;
+extern crate rustc;
 
-use syntax::ast::{Name, TokenTree, Item, MetaItem};
+use syntax::ast::{TokenTree, Item, MetaItem};
 use syntax::codemap::Span;
 use syntax::ext::base::*;
-use syntax::parse::token;
+use rustc::plugin::Registry;
 
-#[macro_registrar]
-pub fn macro_registrar(register: |Name, SyntaxExtension|) {
-    register(token::intern("foo"),
-        NormalTT(box BasicMacroExpander {
-            expander: expand_foo,
-            span: None,
-        },
-        None));
+#[plugin_registrar]
+pub fn plugin_registrar(reg: &mut Registry) {
+    reg.register_macro("foo", expand_foo);
 }
 
 fn expand_foo(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
diff --git a/src/test/auxiliary/weak-lang-items.rs b/src/test/auxiliary/weak-lang-items.rs
index 68a2ae24b85..c998e362d7e 100644
--- a/src/test/auxiliary/weak-lang-items.rs
+++ b/src/test/auxiliary/weak-lang-items.rs
@@ -17,7 +17,7 @@
 #![feature(phase)]
 #![crate_type = "rlib"]
 
-#[phase(syntax, link)]
+#[phase(plugin, link)]
 extern crate core;
 
 struct A;
diff --git a/src/test/bench/shootout-chameneos-redux.rs b/src/test/bench/shootout-chameneos-redux.rs
index baf02feb5b8..28786f1e163 100644
--- a/src/test/bench/shootout-chameneos-redux.rs
+++ b/src/test/bench/shootout-chameneos-redux.rs
@@ -11,7 +11,7 @@
 // no-pretty-expanded
 
 #![feature(phase)]
-#[phase(syntax)] extern crate green;
+#[phase(plugin)] extern crate green;
 
 use std::string::String;
 use std::fmt;
diff --git a/src/test/bench/shootout-meteor.rs b/src/test/bench/shootout-meteor.rs
index 6f4aef27b63..afefaf2b535 100644
--- a/src/test/bench/shootout-meteor.rs
+++ b/src/test/bench/shootout-meteor.rs
@@ -39,7 +39,7 @@
 // OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #![feature(phase)]
-#[phase(syntax)] extern crate green;
+#[phase(plugin)] extern crate green;
 extern crate sync;
 
 use sync::Arc;
diff --git a/src/test/bench/shootout-regex-dna.rs b/src/test/bench/shootout-regex-dna.rs
index c2f0a58a288..ca0248bcf5d 100644
--- a/src/test/bench/shootout-regex-dna.rs
+++ b/src/test/bench/shootout-regex-dna.rs
@@ -46,7 +46,7 @@
 #![feature(macro_rules, phase)]
 
 extern crate regex;
-#[phase(syntax)]extern crate regex_macros;
+#[phase(plugin)]extern crate regex_macros;
 extern crate sync;
 
 use std::io;
diff --git a/src/test/bench/shootout-spectralnorm.rs b/src/test/bench/shootout-spectralnorm.rs
index c038a056569..15b7ff1e81e 100644
--- a/src/test/bench/shootout-spectralnorm.rs
+++ b/src/test/bench/shootout-spectralnorm.rs
@@ -10,7 +10,7 @@
 
 #![feature(phase)]
 #![allow(non_snake_case_functions)]
-#[phase(syntax)] extern crate green;
+#[phase(plugin)] extern crate green;
 extern crate sync;
 
 use std::from_str::FromStr;
diff --git a/src/test/bench/shootout-threadring.rs b/src/test/bench/shootout-threadring.rs
index 1a6582927ca..a001ff78ba0 100644
--- a/src/test/bench/shootout-threadring.rs
+++ b/src/test/bench/shootout-threadring.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 #![feature(phase)]
-#[phase(syntax)] extern crate green;
+#[phase(plugin)] extern crate green;
 green_start!(main)
 
 fn start(n_tasks: int, token: int) {
diff --git a/src/test/compile-fail-fulldeps/gated-phase.rs b/src/test/compile-fail-fulldeps/gated-phase.rs
index c8763899269..1f384b85633 100644
--- a/src/test/compile-fail-fulldeps/gated-phase.rs
+++ b/src/test/compile-fail-fulldeps/gated-phase.rs
@@ -11,7 +11,7 @@
 // aux-build:macro_crate_test.rs
 // ignore-stage1
 
-#[phase(syntax)]
+#[phase(plugin)]
 //~^ ERROR compile time crate loading is experimental and possibly buggy
 extern crate macro_crate_test;
 
diff --git a/src/test/compile-fail-fulldeps/macro-crate-unexported-macro.rs b/src/test/compile-fail-fulldeps/macro-crate-unexported-macro.rs
index f8eb9868a5b..39c2accaddf 100644
--- a/src/test/compile-fail-fulldeps/macro-crate-unexported-macro.rs
+++ b/src/test/compile-fail-fulldeps/macro-crate-unexported-macro.rs
@@ -14,7 +14,7 @@
 
 #![feature(phase)]
 
-#[phase(syntax)]
+#[phase(plugin)]
 extern crate macro_crate_test;
 
 fn main() {
diff --git a/src/test/compile-fail-fulldeps/macro-crate-unknown-crate.rs b/src/test/compile-fail-fulldeps/macro-crate-unknown-crate.rs
index 84c915f267e..7a7eac7b709 100644
--- a/src/test/compile-fail-fulldeps/macro-crate-unknown-crate.rs
+++ b/src/test/compile-fail-fulldeps/macro-crate-unknown-crate.rs
@@ -10,7 +10,7 @@
 
 #![feature(phase)]
 
-#[phase(syntax)]
+#[phase(plugin)]
 extern crate doesnt_exist; //~ ERROR can't find crate
 
 fn main() {}
diff --git a/src/test/compile-fail-fulldeps/phase-syntax-doesnt-resolve.rs b/src/test/compile-fail-fulldeps/phase-syntax-doesnt-resolve.rs
index 2053f81683d..274fbf797e1 100644
--- a/src/test/compile-fail-fulldeps/phase-syntax-doesnt-resolve.rs
+++ b/src/test/compile-fail-fulldeps/phase-syntax-doesnt-resolve.rs
@@ -14,7 +14,7 @@
 
 #![feature(phase)]
 
-#[phase(syntax)]
+#[phase(plugin)]
 extern crate macro_crate_test;
 
 fn main() {
diff --git a/src/test/compile-fail-fulldeps/syntax-extension-fourcc-bad-len.rs b/src/test/compile-fail-fulldeps/syntax-extension-fourcc-bad-len.rs
index fbcdf55f1ac..3ad17618fc0 100644
--- a/src/test/compile-fail-fulldeps/syntax-extension-fourcc-bad-len.rs
+++ b/src/test/compile-fail-fulldeps/syntax-extension-fourcc-bad-len.rs
@@ -13,7 +13,7 @@
 
 #![feature(phase)]
 
-#[phase(syntax)]
+#[phase(plugin)]
 extern crate fourcc;
 
 fn main() {
diff --git a/src/test/compile-fail-fulldeps/syntax-extension-fourcc-invalid-endian.rs b/src/test/compile-fail-fulldeps/syntax-extension-fourcc-invalid-endian.rs
index 569b54b93fb..4d425d9a205 100644
--- a/src/test/compile-fail-fulldeps/syntax-extension-fourcc-invalid-endian.rs
+++ b/src/test/compile-fail-fulldeps/syntax-extension-fourcc-invalid-endian.rs
@@ -13,7 +13,7 @@
 
 #![feature(phase)]
 
-#[phase(syntax)]
+#[phase(plugin)]
 extern crate fourcc;
 
 fn main() {
diff --git a/src/test/compile-fail-fulldeps/syntax-extension-fourcc-non-ascii-str.rs b/src/test/compile-fail-fulldeps/syntax-extension-fourcc-non-ascii-str.rs
index c0e2304354c..1a6d747c1e8 100644
--- a/src/test/compile-fail-fulldeps/syntax-extension-fourcc-non-ascii-str.rs
+++ b/src/test/compile-fail-fulldeps/syntax-extension-fourcc-non-ascii-str.rs
@@ -13,7 +13,7 @@
 
 #![feature(phase)]
 
-#[phase(syntax)]
+#[phase(plugin)]
 extern crate fourcc;
 
 fn main() {
diff --git a/src/test/compile-fail-fulldeps/syntax-extension-fourcc-non-literal.rs b/src/test/compile-fail-fulldeps/syntax-extension-fourcc-non-literal.rs
index 536594f3063..885d8dd1ec3 100644
--- a/src/test/compile-fail-fulldeps/syntax-extension-fourcc-non-literal.rs
+++ b/src/test/compile-fail-fulldeps/syntax-extension-fourcc-non-literal.rs
@@ -13,7 +13,7 @@
 
 #![feature(phase)]
 
-#[phase(syntax)]
+#[phase(plugin)]
 extern crate fourcc;
 
 fn main() {
diff --git a/src/test/compile-fail-fulldeps/syntax-extension-fourcc-unsupported-literal.rs b/src/test/compile-fail-fulldeps/syntax-extension-fourcc-unsupported-literal.rs
index 8a0b0856d24..da1c0070715 100644
--- a/src/test/compile-fail-fulldeps/syntax-extension-fourcc-unsupported-literal.rs
+++ b/src/test/compile-fail-fulldeps/syntax-extension-fourcc-unsupported-literal.rs
@@ -13,7 +13,7 @@
 
 #![feature(phase)]
 
-#[phase(syntax)]
+#[phase(plugin)]
 extern crate fourcc;
 
 fn main() {
diff --git a/src/test/compile-fail-fulldeps/syntax-extension-hexfloat-bad-lits.rs b/src/test/compile-fail-fulldeps/syntax-extension-hexfloat-bad-lits.rs
index 1cd4f654d2e..191042f5f56 100644
--- a/src/test/compile-fail-fulldeps/syntax-extension-hexfloat-bad-lits.rs
+++ b/src/test/compile-fail-fulldeps/syntax-extension-hexfloat-bad-lits.rs
@@ -13,7 +13,7 @@
 
 #![feature(phase)]
 
-#[phase(syntax)]
+#[phase(plugin)]
 extern crate hexfloat;
 
 fn main() {
diff --git a/src/test/compile-fail-fulldeps/syntax-extension-hexfloat-bad-types.rs b/src/test/compile-fail-fulldeps/syntax-extension-hexfloat-bad-types.rs
index 4a6475cea96..f0ace43ec9e 100644
--- a/src/test/compile-fail-fulldeps/syntax-extension-hexfloat-bad-types.rs
+++ b/src/test/compile-fail-fulldeps/syntax-extension-hexfloat-bad-types.rs
@@ -13,7 +13,7 @@
 
 #![feature(phase)]
 
-#[phase(syntax)]
+#[phase(plugin)]
 extern crate hexfloat;
 
 fn main() {
diff --git a/src/test/compile-fail-fulldeps/syntax-extension-regex-invalid.rs b/src/test/compile-fail-fulldeps/syntax-extension-regex-invalid.rs
index 0e072dc1c06..bccba74e05c 100644
--- a/src/test/compile-fail-fulldeps/syntax-extension-regex-invalid.rs
+++ b/src/test/compile-fail-fulldeps/syntax-extension-regex-invalid.rs
@@ -15,7 +15,7 @@
 #![feature(phase)]
 
 extern crate regex;
-#[phase(syntax)] extern crate regex_macros;
+#[phase(plugin)] extern crate regex_macros;
 
 // Tests to make sure that `regex!` will produce a compile error when given
 // an invalid regular expression.
diff --git a/src/test/compile-fail-fulldeps/syntax-extension-regex-unused-static.rs b/src/test/compile-fail-fulldeps/syntax-extension-regex-unused-static.rs
index 300e7e524df..819c9e6b0fe 100644
--- a/src/test/compile-fail-fulldeps/syntax-extension-regex-unused-static.rs
+++ b/src/test/compile-fail-fulldeps/syntax-extension-regex-unused-static.rs
@@ -15,7 +15,7 @@
 #![feature(phase)]
 
 extern crate regex;
-#[phase(syntax)] extern crate regex_macros;
+#[phase(plugin)] extern crate regex_macros;
 
 #[deny(unused_variable)]
 #[deny(dead_code)]
diff --git a/src/test/compile-fail-fulldeps/syntax-extension-regex-unused.rs b/src/test/compile-fail-fulldeps/syntax-extension-regex-unused.rs
index c77bd52d9e5..d96b3f6f224 100644
--- a/src/test/compile-fail-fulldeps/syntax-extension-regex-unused.rs
+++ b/src/test/compile-fail-fulldeps/syntax-extension-regex-unused.rs
@@ -15,7 +15,7 @@
 #![feature(phase)]
 
 extern crate regex;
-#[phase(syntax)] extern crate regex_macros;
+#[phase(plugin)] extern crate regex_macros;
 
 #[deny(unused_variable)]
 #[deny(dead_code)]
diff --git a/src/test/compile-fail/gated-macro_registrar.rs b/src/test/compile-fail/gated-plugin_registrar.rs
index 54274ccb847..f6e11ffd9e5 100644
--- a/src/test/compile-fail/gated-macro_registrar.rs
+++ b/src/test/compile-fail/gated-plugin_registrar.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // the registration function isn't typechecked yet
-#[macro_registrar]
-pub fn registrar() {} //~ ERROR cross-crate macro exports are experimental
+#[plugin_registrar]
+pub fn registrar() {} //~ ERROR compiler plugins are experimental
 
 fn main() {}
diff --git a/src/test/compile-fail/multiple-macro-registrars.rs b/src/test/compile-fail/multiple-plugin-registrars.rs
index 321c0ff0193..f5ebf84b8e0 100644
--- a/src/test/compile-fail/multiple-macro-registrars.rs
+++ b/src/test/compile-fail/multiple-plugin-registrars.rs
@@ -8,15 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: multiple macro registration functions found
+// error-pattern: multiple plugin registration functions found
 
-#![feature(macro_registrar)]
+#![feature(plugin_registrar)]
 
 // the registration function isn't typechecked yet
-#[macro_registrar]
+#[plugin_registrar]
 pub fn one() {}
 
-#[macro_registrar]
+#[plugin_registrar]
 pub fn two() {}
 
 fn main() {}
diff --git a/src/test/run-fail/rt-set-exit-status-fail.rs b/src/test/run-fail/rt-set-exit-status-fail.rs
index 385bc145204..c960679a43f 100644
--- a/src/test/run-fail/rt-set-exit-status-fail.rs
+++ b/src/test/run-fail/rt-set-exit-status-fail.rs
@@ -11,7 +11,7 @@
 // error-pattern:whatever
 
 #![feature(phase)]
-#[phase(syntax, link)] extern crate log;
+#[phase(plugin, link)] extern crate log;
 use std::os;
 
 fn main() {
diff --git a/src/test/run-fail/rt-set-exit-status-fail2.rs b/src/test/run-fail/rt-set-exit-status-fail2.rs
index 3b5e27027b4..22985d57936 100644
--- a/src/test/run-fail/rt-set-exit-status-fail2.rs
+++ b/src/test/run-fail/rt-set-exit-status-fail2.rs
@@ -11,7 +11,7 @@
 // error-pattern:whatever
 
 #![feature(phase)]
-#[phase(syntax, link)] extern crate log;
+#[phase(plugin, link)] extern crate log;
 use std::os;
 use std::task;
 
diff --git a/src/test/run-fail/rt-set-exit-status.rs b/src/test/run-fail/rt-set-exit-status.rs
index b94045e5d12..d08cb198802 100644
--- a/src/test/run-fail/rt-set-exit-status.rs
+++ b/src/test/run-fail/rt-set-exit-status.rs
@@ -11,7 +11,7 @@
 // error-pattern:whatever
 
 #![feature(phase)]
-#[phase(syntax, link)] extern crate log;
+#[phase(plugin, link)] extern crate log;
 use std::os;
 
 fn main() {
diff --git a/src/test/run-make/lto-syntax-extension/main.rs b/src/test/run-make/lto-syntax-extension/main.rs
index 0c55d5fd314..ec4fbca48f8 100644
--- a/src/test/run-make/lto-syntax-extension/main.rs
+++ b/src/test/run-make/lto-syntax-extension/main.rs
@@ -11,7 +11,7 @@
 #![feature(phase)]
 
 extern crate lib;
-#[phase(syntax)] extern crate fourcc;
+#[phase(plugin)] extern crate fourcc;
 
 fn main() {
     fourcc!("1234");
diff --git a/src/test/run-pass-fulldeps/macro-crate-outlive-expansion-phase.rs b/src/test/run-pass-fulldeps/macro-crate-outlive-expansion-phase.rs
index 58663bb44c7..dd585ea9794 100644
--- a/src/test/run-pass-fulldeps/macro-crate-outlive-expansion-phase.rs
+++ b/src/test/run-pass-fulldeps/macro-crate-outlive-expansion-phase.rs
@@ -8,12 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:macro_crate_outlive_expansion_phase.rs
+// aux-build:plugin_crate_outlive_expansion_phase.rs
 // ignore-stage1
 
 #![feature(phase)]
 
-#[phase(syntax)]
-extern crate macro_crate_outlive_expansion_phase;
+#[phase(plugin)]
+extern crate plugin_crate_outlive_expansion_phase;
 
 pub fn main() {}
diff --git a/src/test/run-pass-fulldeps/macro-crate.rs b/src/test/run-pass-fulldeps/macro-crate.rs
index 3c620c5e572..1e796d9d724 100644
--- a/src/test/run-pass-fulldeps/macro-crate.rs
+++ b/src/test/run-pass-fulldeps/macro-crate.rs
@@ -13,7 +13,7 @@
 
 #![feature(phase)]
 
-#[phase(syntax)]
+#[phase(plugin)]
 extern crate macro_crate_test;
 
 #[into_foo]
diff --git a/src/test/run-pass-fulldeps/phase-syntax-link-does-resolve.rs b/src/test/run-pass-fulldeps/phase-syntax-link-does-resolve.rs
index b8d3ab23831..47ff7d31df5 100644
--- a/src/test/run-pass-fulldeps/phase-syntax-link-does-resolve.rs
+++ b/src/test/run-pass-fulldeps/phase-syntax-link-does-resolve.rs
@@ -17,7 +17,7 @@
 
 #![feature(phase)]
 
-#[phase(syntax, link)]
+#[phase(plugin, link)]
 extern crate macro_crate_test;
 
 fn main() {
diff --git a/src/test/run-pass-fulldeps/syntax-extension-fourcc.rs b/src/test/run-pass-fulldeps/syntax-extension-fourcc.rs
index 0681ec63b9e..b16975fe6ee 100644
--- a/src/test/run-pass-fulldeps/syntax-extension-fourcc.rs
+++ b/src/test/run-pass-fulldeps/syntax-extension-fourcc.rs
@@ -13,7 +13,7 @@
 
 #![feature(phase)]
 
-#[phase(syntax)]
+#[phase(plugin)]
 extern crate fourcc;
 
 static static_val: u32 = fourcc!("foo ");
diff --git a/src/test/run-pass-fulldeps/syntax-extension-hexfloat.rs b/src/test/run-pass-fulldeps/syntax-extension-hexfloat.rs
index 3601b610115..496b0111363 100644
--- a/src/test/run-pass-fulldeps/syntax-extension-hexfloat.rs
+++ b/src/test/run-pass-fulldeps/syntax-extension-hexfloat.rs
@@ -12,7 +12,7 @@
 // ignore-pretty
 
 #![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
 extern crate hexfloat;
 
 pub fn main() {
diff --git a/src/test/run-pass-fulldeps/syntax-extension-with-dll-deps.rs b/src/test/run-pass-fulldeps/syntax-extension-with-dll-deps.rs
index efae04ea4fc..275463f5d7f 100644
--- a/src/test/run-pass-fulldeps/syntax-extension-with-dll-deps.rs
+++ b/src/test/run-pass-fulldeps/syntax-extension-with-dll-deps.rs
@@ -14,7 +14,7 @@
 
 #![feature(phase)]
 
-#[phase(syntax)]
+#[phase(plugin)]
 extern crate extension = "syntax-extension-with-dll-deps-2";
 
 fn main() {
diff --git a/src/test/run-pass/capturing-logging.rs b/src/test/run-pass/capturing-logging.rs
index 636e879fe32..3402db7c355 100644
--- a/src/test/run-pass/capturing-logging.rs
+++ b/src/test/run-pass/capturing-logging.rs
@@ -13,7 +13,7 @@
 
 #![feature(phase)]
 
-#[phase(syntax, link)]
+#[phase(plugin, link)]
 extern crate log;
 extern crate native;
 
diff --git a/src/test/run-pass/conditional-debug-macro-off.rs b/src/test/run-pass/conditional-debug-macro-off.rs
index 56b38033c83..b7c4ccb3c2a 100644
--- a/src/test/run-pass/conditional-debug-macro-off.rs
+++ b/src/test/run-pass/conditional-debug-macro-off.rs
@@ -12,7 +12,7 @@
 // exec-env:RUST_LOG=conditional-debug-macro-off=4
 
 #![feature(phase)]
-#[phase(syntax, link)]
+#[phase(plugin, link)]
 extern crate log;
 extern crate debug;
 
diff --git a/src/test/run-pass/deprecated-phase-syntax.rs b/src/test/run-pass/deprecated-phase-syntax.rs
new file mode 100644
index 00000000000..df835dab4d4
--- /dev/null
+++ b/src/test/run-pass/deprecated-phase-syntax.rs
@@ -0,0 +1,19 @@
+// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(phase)]
+
+//~ WARNING phase(syntax) is a deprecated synonym for phase(plugin)
+#[phase(syntax, link)]
+extern crate log;
+
+fn main() {
+    debug!("foo");
+}
diff --git a/src/test/run-pass/issue-14456.rs b/src/test/run-pass/issue-14456.rs
index 79203503373..96290386ccc 100644
--- a/src/test/run-pass/issue-14456.rs
+++ b/src/test/run-pass/issue-14456.rs
@@ -10,7 +10,7 @@
 
 #![feature(phase)]
 
-#[phase(syntax, link)]
+#[phase(plugin, link)]
 extern crate green;
 extern crate native;
 
diff --git a/src/test/run-pass/logging-enabled-debug.rs b/src/test/run-pass/logging-enabled-debug.rs
index 9320c77a285..7975af434d2 100644
--- a/src/test/run-pass/logging-enabled-debug.rs
+++ b/src/test/run-pass/logging-enabled-debug.rs
@@ -12,7 +12,7 @@
 // exec-env:RUST_LOG=logging-enabled-debug=debug
 
 #![feature(phase)]
-#[phase(syntax, link)]
+#[phase(plugin, link)]
 extern crate log;
 
 pub fn main() {
diff --git a/src/test/run-pass/logging-enabled.rs b/src/test/run-pass/logging-enabled.rs
index b1d24e8b9b6..184ac713c89 100644
--- a/src/test/run-pass/logging-enabled.rs
+++ b/src/test/run-pass/logging-enabled.rs
@@ -11,7 +11,7 @@
 // exec-env:RUST_LOG=logging-enabled=info
 
 #![feature(phase)]
-#[phase(syntax, link)]
+#[phase(plugin, link)]
 extern crate log;
 
 pub fn main() {
diff --git a/src/test/run-pass/logging-separate-lines.rs b/src/test/run-pass/logging-separate-lines.rs
index 7f9a4593780..989a8d4bde5 100644
--- a/src/test/run-pass/logging-separate-lines.rs
+++ b/src/test/run-pass/logging-separate-lines.rs
@@ -13,7 +13,7 @@
 
 #![feature(phase)]
 
-#[phase(syntax, link)]
+#[phase(plugin, link)]
 extern crate log;
 
 use std::io::Command;
diff --git a/src/test/run-pass/macro-crate-def-only.rs b/src/test/run-pass/macro-crate-def-only.rs
index abf8edc274c..25da809babd 100644
--- a/src/test/run-pass/macro-crate-def-only.rs
+++ b/src/test/run-pass/macro-crate-def-only.rs
@@ -12,7 +12,7 @@
 
 #![feature(phase)]
 
-#[phase(syntax)]
+#[phase(plugin)]
 extern crate macro_crate_def_only;
 
 pub fn main() {
diff --git a/src/test/run-pass/macro-export-inner-module.rs b/src/test/run-pass/macro-export-inner-module.rs
index 179c65cd046..c7911a69ce4 100644
--- a/src/test/run-pass/macro-export-inner-module.rs
+++ b/src/test/run-pass/macro-export-inner-module.rs
@@ -13,7 +13,7 @@
 
 #![feature(phase)]
 
-#[phase(syntax)]
+#[phase(plugin)]
 extern crate macro_export_inner_module;
 
 pub fn main() {
diff --git a/src/test/run-pass/phase-use-ignored.rs b/src/test/run-pass/phase-use-ignored.rs
index 60f2619fffd..5015e43fa3f 100644
--- a/src/test/run-pass/phase-use-ignored.rs
+++ b/src/test/run-pass/phase-use-ignored.rs
@@ -11,7 +11,7 @@
 
 #![feature(phase)]
 
-#[phase(syntax)]
+#[phase(plugin)]
 use std::mem;
 
 fn main() {}
diff --git a/src/test/run-pass/tcp-stress.rs b/src/test/run-pass/tcp-stress.rs
index a9a6e25adf3..9c4716e5f4d 100644
--- a/src/test/run-pass/tcp-stress.rs
+++ b/src/test/run-pass/tcp-stress.rs
@@ -13,7 +13,7 @@
 // exec-env:RUST_LOG=debug
 
 #![feature(phase)]
-#[phase(syntax, link)]
+#[phase(plugin, link)]
 extern crate log;
 extern crate libc;
 extern crate green;