|
| 1 | +#![feature(rustc_private)] |
| 2 | + |
| 3 | +extern crate getopts; |
| 4 | +extern crate owning_ref; |
| 5 | +extern crate flate2; |
| 6 | + |
| 7 | +extern crate syntax; |
| 8 | +extern crate rustc_data_structures; |
| 9 | + |
| 10 | +extern crate rustc; |
| 11 | +extern crate rustc_back; |
| 12 | +extern crate rustc_errors; |
| 13 | +extern crate rustc_metadata; |
| 14 | +extern crate rustc_incremental; |
| 15 | +extern crate rustc_trans; |
| 16 | +extern crate rustc_driver; |
| 17 | +extern crate rustc_trans_utils; |
| 18 | + |
| 19 | +use std::path::{Path, PathBuf}; |
| 20 | + |
| 21 | +use rustc::ty::TyCtxt; |
| 22 | +use rustc::session::Session; |
| 23 | +use rustc_metadata::cstore::CrateMetadata; |
| 24 | +use rustc_driver::{Compilation, RustcDefaultCalls}; |
| 25 | +use rustc_driver::driver::CompileController; |
| 26 | + |
| 27 | +fn find_sysroot() -> String { |
| 28 | + if let Ok(sysroot) = std::env::var("MIRI_SYSROOT") { |
| 29 | + return sysroot; |
| 30 | + } |
| 31 | + |
| 32 | + // Taken from https://github.com/Manishearth/rust-clippy/pull/911. |
| 33 | + let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME")); |
| 34 | + let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN")); |
| 35 | + match (home, toolchain) { |
| 36 | + (Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain), |
| 37 | + _ => { |
| 38 | + option_env!("RUST_SYSROOT") |
| 39 | + .expect( |
| 40 | + "need to specify RUST_SYSROOT env var or use rustup or multirust", |
| 41 | + ) |
| 42 | + .to_owned() |
| 43 | + } |
| 44 | + } |
| 45 | +} |
| 46 | + |
| 47 | +fn main() { |
| 48 | + let rlib = ::std::env::args().skip(1).next().expect("No rlib given"); |
| 49 | + println!("Reading rlib {}", rlib); |
| 50 | + |
| 51 | + let mut args = ::std::env::args().collect::<Vec<_>>(); |
| 52 | + let sysroot_flag = String::from("--sysroot"); |
| 53 | + if !args.contains(&sysroot_flag) { |
| 54 | + args.push(sysroot_flag); |
| 55 | + args.push(find_sysroot()); |
| 56 | + } |
| 57 | + println!("Rust args: {:?}", args); |
| 58 | + rustc_driver::run_compiler( |
| 59 | + &args, |
| 60 | + &mut MyCompilerCalls(RustcDefaultCalls, rlib.to_string()), |
| 61 | + Some(Box::new(MyFileLoader(rlib.to_string())) as Box<_>), |
| 62 | + None |
| 63 | + ); |
| 64 | +} |
| 65 | + |
| 66 | +struct MyFileLoader(String); |
| 67 | + |
| 68 | +impl syntax::codemap::FileLoader for MyFileLoader { |
| 69 | + fn file_exists(&self, _: &Path) -> bool { true } |
| 70 | + fn abs_path(&self, _: &Path) -> Option<PathBuf> { None } |
| 71 | + fn read_file(&self, _: &Path) -> Result<String, ::std::io::Error> { |
| 72 | + Ok(format!(" |
| 73 | + #![feature(no_core)] |
| 74 | + #![feature(rustc_private)] |
| 75 | + #![feature(panic_unwind)] |
| 76 | + #![feature(panic_abort)] |
| 77 | + #![feature(compiler_builtins_lib)] |
| 78 | + #![no_core] |
| 79 | + extern crate {}; |
| 80 | + fn main() {{}}", self.0)) |
| 81 | + } |
| 82 | +} |
| 83 | + |
| 84 | +struct MyCompilerCalls(RustcDefaultCalls, String); |
| 85 | + |
| 86 | +impl<'a> rustc_driver::CompilerCalls<'a> for MyCompilerCalls { |
| 87 | + fn build_controller( |
| 88 | + &mut self, |
| 89 | + sess: &Session, |
| 90 | + matches: &getopts::Matches |
| 91 | + ) -> CompileController<'a> { |
| 92 | + let mut control = self.0.build_controller(sess, matches); |
| 93 | + control.after_analysis.stop = Compilation::Stop; |
| 94 | + control.after_analysis.callback = Box::new(|state|{ |
| 95 | + let tcx = state.tcx.as_ref().unwrap(); |
| 96 | + let mut extern_crate = None; |
| 97 | + for item in tcx.hir.krate().items.values() { |
| 98 | + match item.node { |
| 99 | + ::rustc::hir::Item_::ItemExternCrate(_) => { |
| 100 | + extern_crate = Some(item.id); |
| 101 | + break; |
| 102 | + } |
| 103 | + _ => {} |
| 104 | + } |
| 105 | + } |
| 106 | + let ext_cnum = tcx.extern_mod_stmt_cnum(tcx.hir.local_def_id(extern_crate.unwrap())).unwrap(); |
| 107 | + let crate_data = tcx.crate_data_as_rc_any(ext_cnum); |
| 108 | + let crate_data = crate_data.downcast_ref::<CrateMetadata>().unwrap(); |
| 109 | + print_metadata(*tcx, crate_data); |
| 110 | + }); |
| 111 | + control |
| 112 | + } |
| 113 | +} |
| 114 | + |
| 115 | +macro_rules! language_item_table { |
| 116 | + ( $( $variant:ident,$name:expr,$_method:ident; )* ) => { |
| 117 | + fn lang_item_name(lang_item: ::rustc::middle::lang_items::LangItem) -> &'static str { |
| 118 | + use rustc::middle::lang_items::LangItem; |
| 119 | + match lang_item { |
| 120 | + $( |
| 121 | + LangItem::$variant => $name |
| 122 | + ),* |
| 123 | + } |
| 124 | + } |
| 125 | + }; |
| 126 | +} |
| 127 | + |
| 128 | +// Copied from librustc/middle/lang_items.rs |
| 129 | +language_item_table! { |
| 130 | +// Variant name, Name, Method name; |
| 131 | + CharImplItem, "char", char_impl; |
| 132 | + StrImplItem, "str", str_impl; |
| 133 | + SliceImplItem, "slice", slice_impl; |
| 134 | + SliceU8ImplItem, "slice_u8", slice_u8_impl; |
| 135 | + ConstPtrImplItem, "const_ptr", const_ptr_impl; |
| 136 | + MutPtrImplItem, "mut_ptr", mut_ptr_impl; |
| 137 | + I8ImplItem, "i8", i8_impl; |
| 138 | + I16ImplItem, "i16", i16_impl; |
| 139 | + I32ImplItem, "i32", i32_impl; |
| 140 | + I64ImplItem, "i64", i64_impl; |
| 141 | + I128ImplItem, "i128", i128_impl; |
| 142 | + IsizeImplItem, "isize", isize_impl; |
| 143 | + U8ImplItem, "u8", u8_impl; |
| 144 | + U16ImplItem, "u16", u16_impl; |
| 145 | + U32ImplItem, "u32", u32_impl; |
| 146 | + U64ImplItem, "u64", u64_impl; |
| 147 | + U128ImplItem, "u128", u128_impl; |
| 148 | + UsizeImplItem, "usize", usize_impl; |
| 149 | + F32ImplItem, "f32", f32_impl; |
| 150 | + F64ImplItem, "f64", f64_impl; |
| 151 | + |
| 152 | + SizedTraitLangItem, "sized", sized_trait; |
| 153 | + UnsizeTraitLangItem, "unsize", unsize_trait; |
| 154 | + CopyTraitLangItem, "copy", copy_trait; |
| 155 | + CloneTraitLangItem, "clone", clone_trait; |
| 156 | + SyncTraitLangItem, "sync", sync_trait; |
| 157 | + FreezeTraitLangItem, "freeze", freeze_trait; |
| 158 | + |
| 159 | + DropTraitLangItem, "drop", drop_trait; |
| 160 | + |
| 161 | + CoerceUnsizedTraitLangItem, "coerce_unsized", coerce_unsized_trait; |
| 162 | + |
| 163 | + AddTraitLangItem, "add", add_trait; |
| 164 | + SubTraitLangItem, "sub", sub_trait; |
| 165 | + MulTraitLangItem, "mul", mul_trait; |
| 166 | + DivTraitLangItem, "div", div_trait; |
| 167 | + RemTraitLangItem, "rem", rem_trait; |
| 168 | + NegTraitLangItem, "neg", neg_trait; |
| 169 | + NotTraitLangItem, "not", not_trait; |
| 170 | + BitXorTraitLangItem, "bitxor", bitxor_trait; |
| 171 | + BitAndTraitLangItem, "bitand", bitand_trait; |
| 172 | + BitOrTraitLangItem, "bitor", bitor_trait; |
| 173 | + ShlTraitLangItem, "shl", shl_trait; |
| 174 | + ShrTraitLangItem, "shr", shr_trait; |
| 175 | + AddAssignTraitLangItem, "add_assign", add_assign_trait; |
| 176 | + SubAssignTraitLangItem, "sub_assign", sub_assign_trait; |
| 177 | + MulAssignTraitLangItem, "mul_assign", mul_assign_trait; |
| 178 | + DivAssignTraitLangItem, "div_assign", div_assign_trait; |
| 179 | + RemAssignTraitLangItem, "rem_assign", rem_assign_trait; |
| 180 | + BitXorAssignTraitLangItem, "bitxor_assign", bitxor_assign_trait; |
| 181 | + BitAndAssignTraitLangItem, "bitand_assign", bitand_assign_trait; |
| 182 | + BitOrAssignTraitLangItem, "bitor_assign", bitor_assign_trait; |
| 183 | + ShlAssignTraitLangItem, "shl_assign", shl_assign_trait; |
| 184 | + ShrAssignTraitLangItem, "shr_assign", shr_assign_trait; |
| 185 | + IndexTraitLangItem, "index", index_trait; |
| 186 | + IndexMutTraitLangItem, "index_mut", index_mut_trait; |
| 187 | + |
| 188 | + UnsafeCellTypeLangItem, "unsafe_cell", unsafe_cell_type; |
| 189 | + |
| 190 | + DerefTraitLangItem, "deref", deref_trait; |
| 191 | + DerefMutTraitLangItem, "deref_mut", deref_mut_trait; |
| 192 | + |
| 193 | + FnTraitLangItem, "fn", fn_trait; |
| 194 | + FnMutTraitLangItem, "fn_mut", fn_mut_trait; |
| 195 | + FnOnceTraitLangItem, "fn_once", fn_once_trait; |
| 196 | + |
| 197 | + GeneratorStateLangItem, "generator_state", gen_state; |
| 198 | + GeneratorTraitLangItem, "generator", gen_trait; |
| 199 | + |
| 200 | + EqTraitLangItem, "eq", eq_trait; |
| 201 | + OrdTraitLangItem, "ord", ord_trait; |
| 202 | + |
| 203 | + // A number of panic-related lang items. The `panic` item corresponds to |
| 204 | + // divide-by-zero and various panic cases with `match`. The |
| 205 | + // `panic_bounds_check` item is for indexing arrays. |
| 206 | + // |
| 207 | + // The `begin_unwind` lang item has a predefined symbol name and is sort of |
| 208 | + // a "weak lang item" in the sense that a crate is not required to have it |
| 209 | + // defined to use it, but a final product is required to define it |
| 210 | + // somewhere. Additionally, there are restrictions on crates that use a weak |
| 211 | + // lang item, but do not have it defined. |
| 212 | + PanicFnLangItem, "panic", panic_fn; |
| 213 | + PanicBoundsCheckFnLangItem, "panic_bounds_check", panic_bounds_check_fn; |
| 214 | + PanicFmtLangItem, "panic_fmt", panic_fmt; |
| 215 | + |
| 216 | + ExchangeMallocFnLangItem, "exchange_malloc", exchange_malloc_fn; |
| 217 | + BoxFreeFnLangItem, "box_free", box_free_fn; |
| 218 | + DropInPlaceFnLangItem, "drop_in_place", drop_in_place_fn; |
| 219 | + |
| 220 | + StartFnLangItem, "start", start_fn; |
| 221 | + |
| 222 | + EhPersonalityLangItem, "eh_personality", eh_personality; |
| 223 | + EhUnwindResumeLangItem, "eh_unwind_resume", eh_unwind_resume; |
| 224 | + MSVCTryFilterLangItem, "msvc_try_filter", msvc_try_filter; |
| 225 | + |
| 226 | + OwnedBoxLangItem, "owned_box", owned_box; |
| 227 | + |
| 228 | + PhantomDataItem, "phantom_data", phantom_data; |
| 229 | + |
| 230 | + NonZeroItem, "non_zero", non_zero; |
| 231 | + |
| 232 | + DebugTraitLangItem, "debug_trait", debug_trait; |
| 233 | + |
| 234 | + // A lang item for each of the 128-bit operators we can optionally lower. |
| 235 | + I128AddFnLangItem, "i128_add", i128_add_fn; |
| 236 | + U128AddFnLangItem, "u128_add", u128_add_fn; |
| 237 | + I128SubFnLangItem, "i128_sub", i128_sub_fn; |
| 238 | + U128SubFnLangItem, "u128_sub", u128_sub_fn; |
| 239 | + I128MulFnLangItem, "i128_mul", i128_mul_fn; |
| 240 | + U128MulFnLangItem, "u128_mul", u128_mul_fn; |
| 241 | + I128DivFnLangItem, "i128_div", i128_div_fn; |
| 242 | + U128DivFnLangItem, "u128_div", u128_div_fn; |
| 243 | + I128RemFnLangItem, "i128_rem", i128_rem_fn; |
| 244 | + U128RemFnLangItem, "u128_rem", u128_rem_fn; |
| 245 | + I128ShlFnLangItem, "i128_shl", i128_shl_fn; |
| 246 | + U128ShlFnLangItem, "u128_shl", u128_shl_fn; |
| 247 | + I128ShrFnLangItem, "i128_shr", i128_shr_fn; |
| 248 | + U128ShrFnLangItem, "u128_shr", u128_shr_fn; |
| 249 | + // And overflow versions for the operators that are checkable. |
| 250 | + // While MIR calls these Checked*, they return (T,bool), not Option<T>. |
| 251 | + I128AddoFnLangItem, "i128_addo", i128_addo_fn; |
| 252 | + U128AddoFnLangItem, "u128_addo", u128_addo_fn; |
| 253 | + I128SuboFnLangItem, "i128_subo", i128_subo_fn; |
| 254 | + U128SuboFnLangItem, "u128_subo", u128_subo_fn; |
| 255 | + I128MuloFnLangItem, "i128_mulo", i128_mulo_fn; |
| 256 | + U128MuloFnLangItem, "u128_mulo", u128_mulo_fn; |
| 257 | + I128ShloFnLangItem, "i128_shlo", i128_shlo_fn; |
| 258 | + U128ShloFnLangItem, "u128_shlo", u128_shlo_fn; |
| 259 | + I128ShroFnLangItem, "i128_shro", i128_shro_fn; |
| 260 | + U128ShroFnLangItem, "u128_shro", u128_shro_fn; |
| 261 | +} |
| 262 | + |
| 263 | +fn print_metadata(tcx: TyCtxt, crate_data: &CrateMetadata) { |
| 264 | + use rustc::middle::lang_items::LangItem; |
| 265 | + use rustc_metadata::cstore::NativeLibraryKind; |
| 266 | + |
| 267 | + macro_rules! svmeta { |
| 268 | + ( @one $crate_data:expr; if $name:ident) => { |
| 269 | + if $crate_data.$name() { |
| 270 | + svmeta!(@print $name, $crate_data.$name()); |
| 271 | + } |
| 272 | + }; |
| 273 | + ( @one $crate_data:expr; if $name:ident ($arg:expr)) => { |
| 274 | + if $crate_data.$name($arg) { |
| 275 | + svmeta!(@print $name, $crate_data.$name($arg)); |
| 276 | + } |
| 277 | + }; |
| 278 | + ( @one $crate_data:expr; $name:ident) => { |
| 279 | + svmeta!(@print $name, $crate_data.$name()); |
| 280 | + }; |
| 281 | + ( @one $crate_data:expr; $name:ident ($arg:expr)) => { |
| 282 | + svmeta!(@print $name, $crate_data.$name($arg)); |
| 283 | + }; |
| 284 | + ( @one $crate_data:expr; $name:ident . $call:ident) => { |
| 285 | + svmeta!(@print $name, $crate_data.$name().$call()); |
| 286 | + }; |
| 287 | + ( @print $name:ident, $val:expr) => { |
| 288 | + let name = stringify!($name); |
| 289 | + println!("{:<30}: {}", name, $val); |
| 290 | + }; |
| 291 | + ( $crate_data:expr; $( ($($tts:tt)*) )* ) => { |
| 292 | + $( |
| 293 | + svmeta!(@one $crate_data; $($tts)*); |
| 294 | + )* |
| 295 | + }; |
| 296 | + } |
| 297 | + //println!("Name: {}", crate_data.name()); |
| 298 | + //println!("Hash: {}", crate_data.hash()); |
| 299 | + //println!("Disambiguator: {}", crate_data.disambiguator().to_fingerprint()); |
| 300 | + svmeta! { |
| 301 | + crate_data; |
| 302 | + (name) |
| 303 | + (hash) |
| 304 | + (disambiguator.to_fingerprint) |
| 305 | + (needs_allocator(tcx.sess)) |
| 306 | + (if has_global_allocator) |
| 307 | + (if has_default_lib_allocator) |
| 308 | + (if is_panic_runtime(tcx.sess)) |
| 309 | + (if is_compiler_builtins(tcx.sess)) |
| 310 | + (if is_sanitizer_runtime(tcx.sess)) |
| 311 | + (if is_profiler_runtime(tcx.sess)) |
| 312 | + (if is_no_builtins(tcx.sess)) |
| 313 | + (if has_copy_closures(tcx.sess)) |
| 314 | + (if has_clone_closures(tcx.sess)) |
| 315 | + (panic_strategy.desc) |
| 316 | + } |
| 317 | + |
| 318 | + println!("\nLang items:"); |
| 319 | + for lang_item in crate_data.get_lang_items() { |
| 320 | + println!(" {}: {}", |
| 321 | + lang_item_name(LangItem::from_u32(lang_item.1 as u32).unwrap()), |
| 322 | + tcx.absolute_item_path_str(lang_item.0), |
| 323 | + ); |
| 324 | + } |
| 325 | + |
| 326 | + println!("\nExported symbols:"); |
| 327 | + for def_id in crate_data.get_exported_symbols() { |
| 328 | + println!(" {}", tcx.absolute_item_path_str(def_id)); |
| 329 | + } |
| 330 | + |
| 331 | + println!("\nTrait impls:"); |
| 332 | + let mut trait_impls = Vec::new(); |
| 333 | + crate_data.get_implementations_for_trait(None, &mut trait_impls); |
| 334 | + for def_id in trait_impls { |
| 335 | + println!(" {}", tcx.absolute_item_path_str(def_id)); |
| 336 | + } |
| 337 | + |
| 338 | + println!("\nDependent rlibs"); |
| 339 | + for dep in crate_data.root.crate_deps.decode(crate_data) { |
| 340 | + println!(" {:<26}: {:?} ({})", dep.name, dep.kind, dep.hash); |
| 341 | + } |
| 342 | + |
| 343 | + println!("\nNative libraries:"); |
| 344 | + for native_lib in crate_data.get_native_libraries(tcx.sess) { |
| 345 | + println!(" {:<26}: {}", |
| 346 | + native_lib.name, |
| 347 | + match native_lib.kind { |
| 348 | + NativeLibraryKind::NativeStatic => "static lib", |
| 349 | + NativeLibraryKind::NativeStaticNobundle => "static lib, not bundled", |
| 350 | + NativeLibraryKind::NativeFramework => "mac os framework", |
| 351 | + NativeLibraryKind::NativeUnknown => "<unknown>", |
| 352 | + } |
| 353 | + ); |
| 354 | + } |
| 355 | + |
| 356 | + println!("\nDylib dependency formats:"); |
| 357 | + for dylib_deps in crate_data.get_dylib_dependency_formats() { |
| 358 | + let ext_crate_data = tcx.crate_data_as_rc_any(dylib_deps.0); |
| 359 | + let ext_crate_data = ext_crate_data.downcast_ref::<CrateMetadata>().unwrap(); |
| 360 | + println!(" {:<26}: {:?}", ext_crate_data.name(), dylib_deps.1); |
| 361 | + } |
| 362 | +} |
0 commit comments