Skip to content

Commit 328b47d

Browse files
committed
Load macros from external modules
1 parent a5ed0c5 commit 328b47d

39 files changed

+873
-205
lines changed

src/compiletest/header.rs

+4
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,14 @@ pub fn is_test_ignored(config: &config, testfile: &Path) -> bool {
9090
fn xfail_target(config: &config) -> ~str {
9191
~"xfail-" + util::get_os(config.target)
9292
}
93+
fn xfail_stage(config: &config) -> ~str {
94+
~"xfail-" + config.stage_id.split('-').next().unwrap()
95+
}
9396
9497
let val = iter_header(testfile, |ln| {
9598
if parse_name_directive(ln, "xfail-test") { false }
9699
else if parse_name_directive(ln, xfail_target(config)) { false }
100+
else if parse_name_directive(ln, xfail_stage(config)) { false }
97101
else if config.mode == common::mode_pretty &&
98102
parse_name_directive(ln, "xfail-pretty") { false }
99103
else { true }

src/librustc/driver/driver.rs

+21-5
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use lib::llvm::{ContextRef, ModuleRef};
2020
use metadata::common::LinkMeta;
2121
use metadata::{creader, filesearch};
2222
use metadata::cstore::CStore;
23+
use metadata::creader::Loader;
2324
use metadata;
2425
use middle::{trans, freevars, kind, ty, typeck, lint, astencode, reachable};
2526
use middle;
@@ -41,6 +42,7 @@ use syntax::attr;
4142
use syntax::attr::{AttrMetaMethods};
4243
use syntax::codemap;
4344
use syntax::diagnostic;
45+
use syntax::ext::base::CrateLoader;
4446
use syntax::parse;
4547
use syntax::parse::token;
4648
use syntax::print::{pp, pprust};
@@ -163,6 +165,7 @@ pub fn phase_1_parse_input(sess: Session, cfg: ast::CrateConfig, input: &input)
163165
/// standard library and prelude.
164166
pub fn phase_2_configure_and_expand(sess: Session,
165167
cfg: ast::CrateConfig,
168+
loader: &mut CrateLoader,
166169
mut crate: ast::Crate)
167170
-> (ast::Crate, syntax::ast_map::Map) {
168171
let time_passes = sess.time_passes();
@@ -188,9 +191,14 @@ pub fn phase_2_configure_and_expand(sess: Session,
188191
crate = time(time_passes, "configuration 1", crate, |crate|
189192
front::config::strip_unconfigured_items(crate));
190193

191-
crate = time(time_passes, "expansion", crate, |crate|
192-
syntax::ext::expand::expand_crate(sess.parse_sess, cfg.clone(),
193-
crate));
194+
crate = time(time_passes, "expansion", crate, |crate| {
195+
syntax::ext::expand::expand_crate(sess.parse_sess,
196+
loader,
197+
cfg.clone(),
198+
crate)
199+
});
200+
// dump the syntax-time crates
201+
sess.cstore.reset();
194202

195203
// strip again, in case expansion added anything with a #[cfg].
196204
crate = time(time_passes, "configuration 2", crate, |crate|
@@ -248,6 +256,11 @@ pub fn phase_3_run_analysis_passes(sess: Session,
248256
time(time_passes, "looking for entry point", (),
249257
|_| middle::entry::find_entry_point(sess, crate, ast_map));
250258

259+
sess.macro_registrar_fn.with_mut(|r| *r =
260+
time(time_passes, "looking for macro registrar", (), |_|
261+
syntax::ext::registrar::find_macro_registrar(
262+
sess.span_diagnostic, crate)));
263+
251264
let freevars = time(time_passes, "freevar finding", (), |_|
252265
freevars::annotate_freevars(def_map, crate));
253266

@@ -491,7 +504,8 @@ pub fn compile_input(sess: Session, cfg: ast::CrateConfig, input: &input,
491504
let (expanded_crate, ast_map) = {
492505
let crate = phase_1_parse_input(sess, cfg.clone(), input);
493506
if stop_after_phase_1(sess) { return; }
494-
phase_2_configure_and_expand(sess, cfg, crate)
507+
let loader = &mut Loader::new(sess);
508+
phase_2_configure_and_expand(sess, cfg, loader, crate)
495509
};
496510
let outputs = build_output_filenames(input, outdir, output,
497511
expanded_crate.attrs, sess);
@@ -579,7 +593,8 @@ pub fn pretty_print_input(sess: Session,
579593

580594
let (crate, ast_map, is_expanded) = match ppm {
581595
PpmExpanded | PpmExpandedIdentified | PpmTyped => {
582-
let (crate, ast_map) = phase_2_configure_and_expand(sess, cfg, crate);
596+
let loader = &mut Loader::new(sess);
597+
let (crate, ast_map) = phase_2_configure_and_expand(sess, cfg, loader, crate);
583598
(crate, Some(ast_map), true)
584599
}
585600
_ => (crate, None, false)
@@ -912,6 +927,7 @@ pub fn build_session_(sopts: @session::options,
912927
// For a library crate, this is always none
913928
entry_fn: RefCell::new(None),
914929
entry_type: Cell::new(None),
930+
macro_registrar_fn: RefCell::new(None),
915931
span_diagnostic: span_diagnostic_handler,
916932
filesearch: filesearch,
917933
building_library: Cell::new(false),

src/librustc/driver/session.rs

+1
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ pub struct Session_ {
210210
entry_fn: RefCell<Option<(NodeId, codemap::Span)>>,
211211
entry_type: Cell<Option<EntryFnType>>,
212212
span_diagnostic: @diagnostic::SpanHandler,
213+
macro_registrar_fn: RefCell<Option<ast::DefId>>,
213214
filesearch: @filesearch::FileSearch,
214215
building_library: Cell<bool>,
215216
working_dir: Path,

src/librustc/front/feature_gate.rs

+19-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[
4343
("non_ascii_idents", Active),
4444
("thread_local", Active),
4545
("link_args", Active),
46+
("phase", Active),
47+
("macro_registrar", Active),
4648

4749
// These are used to test this portion of the compiler, they don't actually
4850
// mean anything
@@ -114,7 +116,15 @@ impl Visitor<()> for Context {
114116
}
115117
}
116118
}
117-
_ => {}
119+
ast::ViewItemExternMod(..) => {
120+
for attr in i.attrs.iter() {
121+
if "phase" == attr.name() {
122+
self.gate_feature("phase", attr.span,
123+
"compile time crate loading is \
124+
experimental and possibly buggy");
125+
}
126+
}
127+
}
118128
}
119129
visit::walk_view_item(self, i, ())
120130
}
@@ -151,6 +161,14 @@ impl Visitor<()> for Context {
151161
}
152162
}
153163

164+
ast::ItemFn(..) => {
165+
if attr::contains_name(i.attrs, "macro_registrar") {
166+
self.gate_feature("macro_registrar", i.span,
167+
"cross-crate macro exports are \
168+
experimental and possibly buggy");
169+
}
170+
}
171+
154172
_ => {}
155173
}
156174

src/librustc/front/test.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use driver::session;
1515
use front::config;
1616
use front::std_inject::with_version;
17+
use metadata::creader::Loader;
1718

1819
use std::cell::RefCell;
1920
use std::vec;
@@ -38,10 +39,10 @@ struct Test {
3839
should_fail: bool
3940
}
4041

41-
struct TestCtxt {
42+
struct TestCtxt<'a> {
4243
sess: session::Session,
4344
path: RefCell<~[ast::Ident]>,
44-
ext_cx: ExtCtxt,
45+
ext_cx: ExtCtxt<'a>,
4546
testfns: RefCell<~[Test]>,
4647
is_extra: bool,
4748
config: ast::CrateConfig,
@@ -63,11 +64,11 @@ pub fn modify_for_testing(sess: session::Session,
6364
}
6465
}
6566

66-
struct TestHarnessGenerator {
67-
cx: TestCtxt,
67+
struct TestHarnessGenerator<'a> {
68+
cx: TestCtxt<'a>,
6869
}
6970

70-
impl fold::Folder for TestHarnessGenerator {
71+
impl<'a> fold::Folder for TestHarnessGenerator<'a> {
7172
fn fold_crate(&mut self, c: ast::Crate) -> ast::Crate {
7273
let folded = fold::noop_fold_crate(c, self);
7374

@@ -155,9 +156,10 @@ impl fold::Folder for TestHarnessGenerator {
155156

156157
fn generate_test_harness(sess: session::Session, crate: ast::Crate)
157158
-> ast::Crate {
159+
let loader = &mut Loader::new(sess);
158160
let mut cx: TestCtxt = TestCtxt {
159161
sess: sess,
160-
ext_cx: ExtCtxt::new(sess.parse_sess, sess.opts.cfg.clone()),
162+
ext_cx: ExtCtxt::new(sess.parse_sess, sess.opts.cfg.clone(), loader),
161163
path: RefCell::new(~[]),
162164
testfns: RefCell::new(~[]),
163165
is_extra: is_extra(&crate),

src/librustc/metadata/common.rs

+4
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,10 @@ pub static tag_native_libraries_lib: uint = 0x104;
204204
pub static tag_native_libraries_name: uint = 0x105;
205205
pub static tag_native_libraries_kind: uint = 0x106;
206206

207+
pub static tag_macro_registrar_fn: uint = 0x110;
208+
pub static tag_exported_macros: uint = 0x111;
209+
pub static tag_macro_def: uint = 0x112;
210+
207211
#[deriving(Clone)]
208212
pub struct LinkMeta {
209213
crateid: CrateId,

src/librustc/metadata/creader.rs

+105-30
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@
1010

1111
//! Validates all used crates and extern libraries and loads their metadata
1212
13+
use driver::{driver, session};
1314
use driver::session::Session;
15+
use metadata::csearch;
1416
use metadata::cstore;
1517
use metadata::decoder;
1618
use metadata::loader;
19+
use metadata::loader::Os;
1720

1821
use std::cell::RefCell;
1922
use std::hashmap::HashMap;
@@ -23,6 +26,7 @@ use syntax::attr;
2326
use syntax::attr::AttrMetaMethods;
2427
use syntax::codemap::{Span, DUMMY_SP};
2528
use syntax::diagnostic::SpanHandler;
29+
use syntax::ext::base::{CrateLoader, MacroCrate};
2630
use syntax::parse::token;
2731
use syntax::parse::token::IdentInterner;
2832
use syntax::crateid::CrateId;
@@ -131,37 +135,65 @@ fn visit_crate(e: &Env, c: &ast::Crate) {
131135
}
132136

133137
fn visit_view_item(e: &mut Env, i: &ast::ViewItem) {
138+
let should_load = i.attrs.iter().all(|attr| {
139+
"phase" != attr.name() ||
140+
attr.meta_item_list().map_or(false, |phases| {
141+
attr::contains_name(phases, "link")
142+
})
143+
});
144+
145+
if !should_load {
146+
return;
147+
}
148+
149+
match extract_crate_info(i) {
150+
Some(info) => {
151+
let cnum = resolve_crate(e, info.ident, info.name, info.version,
152+
@"", i.span);
153+
e.sess.cstore.add_extern_mod_stmt_cnum(info.id, cnum);
154+
}
155+
None => ()
156+
}
157+
}
158+
159+
struct CrateInfo {
160+
ident: @str,
161+
name: @str,
162+
version: @str,
163+
id: ast::NodeId,
164+
}
165+
166+
fn extract_crate_info(i: &ast::ViewItem) -> Option<CrateInfo> {
134167
match i.node {
135-
ast::ViewItemExternMod(ident, path_opt, id) => {
136-
let ident = token::ident_to_str(&ident);
137-
debug!("resolving extern mod stmt. ident: {:?} path_opt: {:?}",
138-
ident, path_opt);
139-
let (name, version) = match path_opt {
140-
Some((path_str, _)) => {
141-
let crateid: Option<CrateId> = from_str(path_str);
142-
match crateid {
143-
None => (@"", @""),
144-
Some(crateid) => {
145-
let version = match crateid.version {
146-
None => @"",
147-
Some(ref ver) => ver.to_managed(),
148-
};
149-
(crateid.name.to_managed(), version)
150-
}
151-
}
152-
}
153-
None => (ident, @""),
154-
};
155-
let cnum = resolve_crate(e,
156-
ident,
157-
name,
158-
version,
159-
@"",
160-
i.span);
161-
e.sess.cstore.add_extern_mod_stmt_cnum(id, cnum);
162-
}
163-
_ => ()
164-
}
168+
ast::ViewItemExternMod(ident, path_opt, id) => {
169+
let ident = token::ident_to_str(&ident);
170+
debug!("resolving extern mod stmt. ident: {:?} path_opt: {:?}",
171+
ident, path_opt);
172+
let (name, version) = match path_opt {
173+
Some((path_str, _)) => {
174+
let crateid: Option<CrateId> = from_str(path_str);
175+
match crateid {
176+
None => (@"", @""),
177+
Some(crateid) => {
178+
let version = match crateid.version {
179+
None => @"",
180+
Some(ref ver) => ver.to_managed(),
181+
};
182+
(crateid.name.to_managed(), version)
183+
}
184+
}
185+
}
186+
None => (ident, @""),
187+
};
188+
Some(CrateInfo {
189+
ident: ident,
190+
name: name,
191+
version: version,
192+
id: id,
193+
})
194+
}
195+
_ => None
196+
}
165197
}
166198

167199
fn visit_item(e: &Env, i: &ast::Item) {
@@ -355,3 +387,46 @@ fn resolve_crate_deps(e: &mut Env, cdata: &[u8]) -> cstore::cnum_map {
355387
}
356388
return @RefCell::new(cnum_map);
357389
}
390+
391+
pub struct Loader {
392+
priv env: Env,
393+
}
394+
395+
impl Loader {
396+
pub fn new(sess: Session) -> Loader {
397+
let os = driver::get_os(driver::host_triple()).unwrap();
398+
let os = session::sess_os_to_meta_os(os);
399+
Loader {
400+
env: Env {
401+
sess: sess,
402+
os: os,
403+
crate_cache: @RefCell::new(~[]),
404+
next_crate_num: 1,
405+
intr: token::get_ident_interner(),
406+
}
407+
}
408+
}
409+
}
410+
411+
impl CrateLoader for Loader {
412+
fn load_crate(&mut self, crate: &ast::ViewItem) -> MacroCrate {
413+
let info = extract_crate_info(crate).unwrap();
414+
let cnum = resolve_crate(&mut self.env, info.ident, info.name,
415+
info.version, @"", crate.span);
416+
let library = self.env.sess.cstore.get_used_crate_source(cnum).unwrap();
417+
MacroCrate {
418+
lib: library.dylib,
419+
cnum: cnum
420+
}
421+
}
422+
423+
fn get_exported_macros(&mut self, cnum: ast::CrateNum) -> ~[@ast::Item] {
424+
csearch::get_exported_macros(self.env.sess.cstore, cnum)
425+
}
426+
427+
fn get_registrar_symbol(&mut self, cnum: ast::CrateNum) -> Option<~str> {
428+
let cstore = self.env.sess.cstore;
429+
csearch::get_macro_registrar_fn(cstore, cnum)
430+
.map(|did| csearch::get_symbol(cstore, did))
431+
}
432+
}

src/librustc/metadata/csearch.rs

+13
Original file line numberDiff line numberDiff line change
@@ -301,3 +301,16 @@ pub fn get_trait_of_method(cstore: @cstore::CStore,
301301
decoder::get_trait_of_method(cdata, def_id.node, tcx)
302302
}
303303

304+
pub fn get_macro_registrar_fn(cstore: @cstore::CStore,
305+
crate_num: ast::CrateNum)
306+
-> Option<ast::DefId> {
307+
let cdata = cstore.get_crate_data(crate_num);
308+
decoder::get_macro_registrar_fn(cdata)
309+
}
310+
311+
pub fn get_exported_macros(cstore: @cstore::CStore,
312+
crate_num: ast::CrateNum)
313+
-> ~[@ast::Item] {
314+
let cdata = cstore.get_crate_data(crate_num);
315+
decoder::get_exported_macros(cdata)
316+
}

0 commit comments

Comments
 (0)