trans_crate.rs 9.8 KB
Newer Older
B
bjorn3 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
// Copyright 2014-2015 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.

//! The Rust compiler.
//!
//! # Note
//!
//! This API is completely unstable and subject to change.

#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
      html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
      html_root_url = "https://doc.rust-lang.org/nightly/")]
#![deny(warnings)]

#![feature(box_syntax)]

B
bjorn3 已提交
24
use std::any::Any;
25 26 27
use std::io::prelude::*;
use std::io::{self, Cursor};
use std::fs::File;
B
bjorn3 已提交
28
use std::path::Path;
B
Fix ICE  
bjorn3 已提交
29
use std::rc::Rc;
B
bjorn3 已提交
30
use std::sync::mpsc;
B
bjorn3 已提交
31

32
use rustc_data_structures::owning_ref::{ErasedBoxRef, OwningRef};
33 34 35 36 37 38
use ar::{Archive, Builder, Header};
use flate2::Compression;
use flate2::write::DeflateEncoder;

use syntax::symbol::Symbol;
use rustc::hir::def_id::LOCAL_CRATE;
39 40
use rustc::session::{Session, CompileIncomplete};
use rustc::session::config::{CrateType, OutputFilenames, PrintRequest};
B
bjorn3 已提交
41
use rustc::ty::TyCtxt;
B
bjorn3 已提交
42
use rustc::ty::maps::Providers;
43
use rustc::middle::cstore::EncodedMetadata;
B
bjorn3 已提交
44
use rustc::middle::cstore::MetadataLoader;
45
use rustc::dep_graph::DepGraph;
B
bjorn3 已提交
46
use rustc_back::target::Target;
47
use rustc_mir::monomorphize::collector;
48
use link::{build_link_meta, out_filename};
B
bjorn3 已提交
49 50

pub trait TransCrate {
51
    fn init(&self, _sess: &Session) {}
52 53
    fn print(&self, _req: PrintRequest, _sess: &Session) {}
    fn target_features(&self, _sess: &Session) -> Vec<Symbol> { vec![] }
54 55 56
    fn print_passes(&self) {}
    fn print_version(&self) {}
    fn diagnostics(&self) -> &[(&'static str, &'static str)] { &[] }
B
bjorn3 已提交
57

58 59 60
    fn metadata_loader(&self) -> Box<MetadataLoader>;
    fn provide(&self, _providers: &mut Providers);
    fn provide_extern(&self, _providers: &mut Providers);
B
bjorn3 已提交
61
    fn trans_crate<'a, 'tcx>(
62
        &self,
B
bjorn3 已提交
63
        tcx: TyCtxt<'a, 'tcx, 'tcx>,
B
bjorn3 已提交
64
        rx: mpsc::Receiver<Box<Any + Send>>
65 66 67 68 69 70 71 72 73 74
    ) -> Box<Any>;

    /// This is called on the returned `Box<Any>` from `trans_crate`
    ///
    /// # Panics
    ///
    /// Panics when the passed `Box<Any>` was not returned by `trans_crate`.
    fn join_trans_and_link(
        &self,
        trans: Box<Any>,
B
bjorn3 已提交
75
        sess: &Session,
76 77 78
        dep_graph: &DepGraph,
        outputs: &OutputFilenames,
    ) -> Result<(), CompileIncomplete>;
B
bjorn3 已提交
79 80 81 82 83
}

pub struct DummyTransCrate;

impl TransCrate for DummyTransCrate {
84
    fn metadata_loader(&self) -> Box<MetadataLoader> {
B
bjorn3 已提交
85 86 87
        box DummyMetadataLoader(())
    }

88
    fn provide(&self, _providers: &mut Providers) {
89
        bug!("DummyTransCrate::provide");
B
bjorn3 已提交
90 91
    }

92
    fn provide_extern(&self, _providers: &mut Providers) {
B
bjorn3 已提交
93
        bug!("DummyTransCrate::provide_extern");
B
bjorn3 已提交
94 95 96
    }

    fn trans_crate<'a, 'tcx>(
97
        &self,
B
bjorn3 已提交
98
        _tcx: TyCtxt<'a, 'tcx, 'tcx>,
B
bjorn3 已提交
99
        _rx: mpsc::Receiver<Box<Any + Send>>
100
    ) -> Box<Any> {
B
bjorn3 已提交
101 102 103
        bug!("DummyTransCrate::trans_crate");
    }

104 105 106
    fn join_trans_and_link(
        &self,
        _trans: Box<Any>,
B
bjorn3 已提交
107
        _sess: &Session,
108 109 110 111
        _dep_graph: &DepGraph,
        _outputs: &OutputFilenames,
    ) -> Result<(), CompileIncomplete> {
        bug!("DummyTransCrate::join_trans_and_link");
B
bjorn3 已提交
112 113 114 115 116
    }
}

pub struct DummyMetadataLoader(());

117
impl MetadataLoader for DummyMetadataLoader {
B
bjorn3 已提交
118 119 120 121 122
    fn get_rlib_metadata(
        &self,
        _target: &Target,
        _filename: &Path
    ) -> Result<ErasedBoxRef<[u8]>, String> {
B
bjorn3 已提交
123 124 125
        bug!("DummyMetadataLoader::get_rlib_metadata");
    }

B
bjorn3 已提交
126 127 128 129 130
    fn get_dylib_metadata(
        &self,
        _target: &Target,
        _filename: &Path
    ) -> Result<ErasedBoxRef<[u8]>, String> {
B
bjorn3 已提交
131 132 133
        bug!("DummyMetadataLoader::get_dylib_metadata");
    }
}
134 135 136

pub struct NoLlvmMetadataLoader;

137
impl MetadataLoader for NoLlvmMetadataLoader {
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
    fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result<ErasedBoxRef<[u8]>, String> {
        let file = File::open(filename)
            .map_err(|e| format!("metadata file open err: {:?}", e))?;
        let mut archive = Archive::new(file);

        while let Some(entry_result) = archive.next_entry() {
            let mut entry = entry_result
                .map_err(|e| format!("metadata section read err: {:?}", e))?;
            if entry.header().identifier() == "rust.metadata.bin" {
                let mut buf = Vec::new();
                io::copy(&mut entry, &mut buf).unwrap();
                let buf: OwningRef<Vec<u8>, [u8]> = OwningRef::new(buf).into();
                return Ok(buf.map_owner_box().erase_owner());
            }
        }

        Err("Couldnt find metadata section".to_string())
    }

    fn get_dylib_metadata(
        &self,
        _target: &Target,
        _filename: &Path,
    ) -> Result<ErasedBoxRef<[u8]>, String> {
        // FIXME: Support reading dylibs from llvm enabled rustc
        self.get_rlib_metadata(_target, _filename)
    }
}

167
pub struct MetadataOnlyTransCrate(());
168 169 170 171 172 173 174
pub struct OngoingCrateTranslation {
    metadata: EncodedMetadata,
    metadata_version: Vec<u8>,
    crate_name: Symbol,
}

impl MetadataOnlyTransCrate {
175 176 177 178 179 180 181
    pub fn new() -> Box<TransCrate> {
        box MetadataOnlyTransCrate(())
    }
}

impl TransCrate for MetadataOnlyTransCrate {
    fn init(&self, sess: &Session) {
182 183 184 185 186 187 188 189 190 191 192
        for cty in sess.opts.crate_types.iter() {
            match *cty {
                CrateType::CrateTypeRlib | CrateType::CrateTypeDylib |
                CrateType::CrateTypeExecutable => {},
                _ => {
                    sess.parse_sess.span_diagnostic.warn(
                        &format!("LLVM unsupported, so output type {} is not supported", cty)
                    );
                },
            }
        }
193 194
    }

195
    fn metadata_loader(&self) -> Box<MetadataLoader> {
196 197 198
        box NoLlvmMetadataLoader
    }

199 200
    fn provide(&self, providers: &mut Providers) {
        ::symbol_names::provide(providers);
B
Fix ICE  
bjorn3 已提交
201 202 203
        providers.target_features_enabled = |_tcx, _id| {
            Rc::new(Vec::new()) // Just a dummy
        };
204 205
    }
    fn provide_extern(&self, _providers: &mut Providers) {}
206 207

    fn trans_crate<'a, 'tcx>(
208
        &self,
209
        tcx: TyCtxt<'a, 'tcx, 'tcx>,
B
bjorn3 已提交
210
        _rx: mpsc::Receiver<Box<Any + Send>>
211 212 213
    ) -> Box<Any> {
        use rustc_mir::monomorphize::item::MonoItem;

B
bjorn3 已提交
214
        ::check_for_rustc_errors_attr(tcx);
215 216 217 218 219 220 221 222 223 224
        ::symbol_names_test::report_symbol_names(tcx);
        ::rustc_incremental::assert_dep_graph(tcx);
        ::rustc_incremental::assert_module_sources::assert_module_sources(tcx);
        ::rustc_mir::monomorphize::assert_symbols_are_distinct(tcx,
            collector::collect_crate_mono_items(
                tcx,
                collector::MonoItemCollectionMode::Eager
            ).0.iter()
        );
        ::rustc::middle::dependency_format::calculate(tcx);
B
bjorn3 已提交
225 226
        let _ = tcx.link_args(LOCAL_CRATE);
        let _ = tcx.native_libraries(LOCAL_CRATE);
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
        for trans_item in
            collector::collect_crate_mono_items(
                tcx,
                collector::MonoItemCollectionMode::Eager
            ).0 {
            match trans_item {
                MonoItem::Fn(inst) => {
                    let def_id = inst.def_id();
                    if def_id.is_local()  {
                        let _ = tcx.export_name(def_id);
                        let _ = tcx.contains_extern_indicator(def_id);
                        let _ = inst.def.is_inline(tcx);
                        let attrs = inst.def.attrs(tcx);
                        let _ =
                            ::syntax::attr::find_inline_attr(Some(tcx.sess.diagnostic()), &attrs);
                    }
                }
                _ => {}
            }
        }
B
bjorn3 已提交
247 248
        tcx.sess.abort_if_errors();

249
        let link_meta = build_link_meta(tcx.crate_hash(LOCAL_CRATE));
B
bjorn3 已提交
250
        let exported_symbols = ::find_exported_symbols(tcx);
251
        let metadata = tcx.encode_metadata(&link_meta, &exported_symbols);
252

253
        box OngoingCrateTranslation {
254 255 256 257 258 259
            metadata: metadata,
            metadata_version: tcx.metadata_encoding_version().to_vec(),
            crate_name: tcx.crate_name(LOCAL_CRATE),
        }
    }

260 261 262 263
    fn join_trans_and_link(
        &self,
        trans: Box<Any>,
        sess: &Session,
264
        _dep_graph: &DepGraph,
265 266 267 268
        outputs: &OutputFilenames,
    ) -> Result<(), CompileIncomplete> {
        let trans = trans.downcast::<OngoingCrateTranslation>()
            .expect("Expected MetadataOnlyTransCrate's OngoingCrateTranslation, found Box<Any>");
269 270 271 272 273
        for &crate_type in sess.opts.crate_types.iter() {
            if crate_type != CrateType::CrateTypeRlib && crate_type != CrateType::CrateTypeDylib {
                continue;
            }
            let output_name =
274 275
                out_filename(sess, crate_type, &outputs, &trans.crate_name.as_str());
            let mut compressed = trans.metadata_version.clone();
276
            let metadata = if crate_type == CrateType::CrateTypeDylib {
277
                DeflateEncoder::new(&mut compressed, Compression::fast())
278
                    .write_all(&trans.metadata.raw_data)
279 280 281
                    .unwrap();
                &compressed
            } else {
282
                &trans.metadata.raw_data
283 284 285 286 287 288
            };
            let mut builder = Builder::new(File::create(&output_name).unwrap());
            let header = Header::new("rust.metadata.bin".to_string(), metadata.len() as u64);
            builder.append(&header, Cursor::new(metadata)).unwrap();
        }

289
        sess.abort_if_errors();
290
        if !sess.opts.crate_types.contains(&CrateType::CrateTypeRlib)
291 292
            && !sess.opts.crate_types.contains(&CrateType::CrateTypeDylib)
        {
293 294
            sess.fatal("Executables are not supported by the metadata-only backend.");
        }
295
        Ok(())
296 297
    }
}