diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..ea8c4bf7f3 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/rspirv-linker/Cargo.lock b/Cargo.lock similarity index 86% rename from rspirv-linker/Cargo.lock rename to Cargo.lock index 47045e4587..1c8285f6e3 100644 --- a/rspirv-linker/Cargo.lock +++ b/Cargo.lock @@ -49,7 +49,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39858aa5bac06462d4dd4b9164848eb81ffc4aa5c479746393598fd193afa227" dependencies = [ "quote 1.0.7", - "syn 1.0.39", + "syn 1.0.40", ] [[package]] @@ -72,6 +72,18 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" +[[package]] +name = "filetime" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed85775dcc68644b5c950ac06a2b23768d3bc9390464151aaf27136998dcf9e" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "winapi", +] + [[package]] name = "fxhash" version = "0.2.1" @@ -83,9 +95,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" +checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6" dependencies = [ "cfg-if", "libc", @@ -100,9 +112,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.76" +version = "0.2.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "755456fae044e6fa1ebbbd1b3e902ae19e73097ed4ed87bb79934a867c007bc3" +checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235" [[package]] name = "memchr" @@ -157,9 +169,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.19" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12" +checksum = "36e28516df94f3dd551a587da5357459d9b36d945a7c37c3557928c1c2ff2a2c" dependencies = [ "unicode-xid 0.2.1", ] @@ -179,7 +191,7 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" dependencies = [ - "proc-macro2 1.0.19", + "proc-macro2 1.0.21", ] [[package]] @@ -259,6 +271,7 @@ dependencies = [ [[package]] name = "rspirv" version = "0.7.0" +source = "git+https://github.com/gfx-rs/rspirv#25737220af8703f2b48edd368e63f413f3dfd0e4" dependencies = [ "derive_more", "fxhash", @@ -277,6 +290,18 @@ dependencies = [ "topological-sort", ] +[[package]] +name = "rustc_codegen_spirv" +version = "0.1.0" +dependencies = [ + "pretty_assertions", + "rspirv", + "rspirv-linker", + "tar", + "tempfile", + "topological-sort", +] + [[package]] name = "rustc_version" version = "0.2.3" @@ -304,6 +329,7 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "spirv_headers" version = "1.5.0" +source = "git+https://github.com/gfx-rs/rspirv#25737220af8703f2b48edd368e63f413f3dfd0e4" dependencies = [ "bitflags", "num-traits", @@ -322,15 +348,27 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.39" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891d8d6567fe7c7f8835a3a98af4208f3846fba258c1bc3c31d6e506239f11f9" +checksum = "963f7d3cc59b59b9325165add223142bbf1df27655d07789f109896d353d8350" dependencies = [ - "proc-macro2 1.0.19", + "proc-macro2 1.0.21", "quote 1.0.7", "unicode-xid 0.2.1", ] +[[package]] +name = "tar" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "489997b7557e9a43e192c527face4feacc78bfbe6eed67fd55c4c9e381cba290" +dependencies = [ + "filetime", + "libc", + "redox_syscall", + "xattr", +] + [[package]] name = "tempfile" version = "3.1.0" @@ -360,9 +398,9 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd80fc12f73063ac132ac92aceea36734f04a1d93c1240c6944e23a3b8841793" dependencies = [ - "proc-macro2 1.0.19", + "proc-macro2 1.0.21", "quote 1.0.7", - "syn 1.0.39", + "syn 1.0.40", ] [[package]] @@ -419,3 +457,12 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "xattr" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c" +dependencies = [ + "libc", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000000..7c41012872 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,5 @@ +[workspace] +members = [ + "rustc_codegen_spirv", + "rspirv-linker", +] diff --git a/rspirv-linker/Cargo.toml b/rspirv-linker/Cargo.toml index ff8cb3a032..30ec9d2c48 100644 --- a/rspirv-linker/Cargo.toml +++ b/rspirv-linker/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rspirv = { path = "C:/Users/Jasper/traverse/rspirv/rspirv/"} +rspirv = { git = "https://github.com/gfx-rs/rspirv" } topological-sort = "0.1" thiserror = "1.0.20" diff --git a/rspirv-linker/src/main.rs b/rspirv-linker/src/lib.rs similarity index 99% rename from rspirv-linker/src/main.rs rename to rspirv-linker/src/lib.rs index 6801782f3c..047ffda419 100644 --- a/rspirv-linker/src/main.rs +++ b/rspirv-linker/src/lib.rs @@ -1,3 +1,4 @@ +#[cfg(test)] mod test; use rspirv::binary::Consumer; @@ -410,12 +411,12 @@ fn import_kill_annotations_and_debug(module: &mut rspirv::dr::Module, info: &Lin } } -struct Options { +pub struct Options { /// `true` if we're creating a library - lib: bool, + pub lib: bool, /// `true` if partial linking is allowed - partial: bool, + pub partial: bool, } impl Default for Options { @@ -769,7 +770,7 @@ fn trans_aggregate_type( }) } -fn link(inputs: &mut [&mut rspirv::dr::Module], opts: &Options) -> Result { +pub fn link(inputs: &mut [&mut rspirv::dr::Module], opts: &Options) -> Result { // shift all the ids let mut bound = inputs[0].header.as_ref().unwrap().bound - 1; diff --git a/rustc_codegen_spirv/rust-toolchain b/rust-toolchain similarity index 100% rename from rustc_codegen_spirv/rust-toolchain rename to rust-toolchain diff --git a/rustc_codegen_spirv/.gitignore b/rustc_codegen_spirv/.gitignore deleted file mode 100644 index 2d45a6edf3..0000000000 --- a/rustc_codegen_spirv/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/target -Cargo.lock -*.spv diff --git a/rustc_codegen_spirv/Cargo.toml b/rustc_codegen_spirv/Cargo.toml index d589c7e75b..edeb61019f 100644 --- a/rustc_codegen_spirv/Cargo.toml +++ b/rustc_codegen_spirv/Cargo.toml @@ -14,6 +14,8 @@ crate-type = ["dylib"] [dependencies] rspirv = { git = "https://github.com/gfx-rs/rspirv" } +rspirv-linker = { path = "../rspirv-linker" } +tar = "0.4" topological-sort = "0.1" [dev-dependencies] diff --git a/rustc_codegen_spirv/build_libcore_test.sh b/rustc_codegen_spirv/build_libcore_test.sh index 693c5766d6..401f2c3ef3 100755 --- a/rustc_codegen_spirv/build_libcore_test.sh +++ b/rustc_codegen_spirv/build_libcore_test.sh @@ -6,7 +6,7 @@ set -e # build rustc_codegen_spirv cargo build -export RUSTFLAGS=-Zcodegen-backend=$PWD/target/debug/librustc_codegen_spirv.so +export RUSTFLAGS=-Zcodegen-backend=$PWD/../target/debug/librustc_codegen_spirv.so pushd build_libcore_test # Use wasm32 because it's a relatively simple platform - if the x86 libcore is used, there's all sorts of "feature sse2 diff --git a/rustc_codegen_spirv/build_libcore_test/.gitignore b/rustc_codegen_spirv/build_libcore_test/.gitignore index b83d22266a..e9e21997b1 100644 --- a/rustc_codegen_spirv/build_libcore_test/.gitignore +++ b/rustc_codegen_spirv/build_libcore_test/.gitignore @@ -1 +1,2 @@ /target/ +/Cargo.lock diff --git a/rustc_codegen_spirv/build_libcore_test/Cargo.toml b/rustc_codegen_spirv/build_libcore_test/Cargo.toml index 6eab81b281..3ff7ede610 100644 --- a/rustc_codegen_spirv/build_libcore_test/Cargo.toml +++ b/rustc_codegen_spirv/build_libcore_test/Cargo.toml @@ -4,4 +4,9 @@ version = "0.1.0" authors = ["Ashley Hauck "] edition = "2018" +[lib] +crate-type = ["cdylib"] + [dependencies] + +[workspace] diff --git a/rustc_codegen_spirv/src/builder_spirv.rs b/rustc_codegen_spirv/src/builder_spirv.rs index 2a73b63e9f..e3dd07f531 100644 --- a/rustc_codegen_spirv/src/builder_spirv.rs +++ b/rustc_codegen_spirv/src/builder_spirv.rs @@ -73,15 +73,9 @@ impl BuilderSpirv { let disas = module.disassemble(); println!("{}", disas); let spirv_module = module.assemble(); - let spirv_module_u8: &[u8] = unsafe { - std::slice::from_raw_parts( - spirv_module.as_ptr() as *const u8, - spirv_module.len() * std::mem::size_of::(), - ) - }; File::create(path) .unwrap() - .write_all(spirv_module_u8) + .write_all(crate::slice_u32_to_u8(&spirv_module)) .unwrap(); } diff --git a/rustc_codegen_spirv/src/codegen_cx.rs b/rustc_codegen_spirv/src/codegen_cx.rs index 22603cc7ff..f6ec4a6086 100644 --- a/rustc_codegen_spirv/src/codegen_cx.rs +++ b/rustc_codegen_spirv/src/codegen_cx.rs @@ -724,15 +724,22 @@ impl<'tcx> PreDefineMethods<'tcx> for CodegenCx<'tcx> { fn predefine_fn( &self, instance: Instance<'tcx>, - _linkage: Linkage, + linkage: Linkage, visibility: Visibility, symbol_name: &str, ) { let fn_abi = FnAbi::of_instance(self, instance, &[]); let human_name = format!("{}", instance); + if symbol_name == "_ZN51_$LT$i32$u20$as$u20$compiler_builtins..int..Int$GT$12extract_sign17h33d8e137c5cab7faE" { + println!("{} = {:?} {:?}", human_name, linkage, visibility); + } let linkage = match visibility { Visibility::Default | Visibility::Protected => Some(LinkageType::Export), - Visibility::Hidden => None, + Visibility::Hidden => match linkage { + Linkage::External | Linkage::AvailableExternally => Some(LinkageType::Export), + // TODO: Figure out linkage types + _ => None, + }, }; let declared = declare_fn(self, symbol_name, Some(&human_name), linkage, &fn_abi); self.instances.borrow_mut().insert(instance, declared); diff --git a/rustc_codegen_spirv/src/lib.rs b/rustc_codegen_spirv/src/lib.rs index 6fa40718f3..57180b5bbc 100644 --- a/rustc_codegen_spirv/src/lib.rs +++ b/rustc_codegen_spirv/src/lib.rs @@ -2,14 +2,17 @@ #![feature(once_cell)] extern crate rustc_ast; +extern crate rustc_attr; extern crate rustc_codegen_ssa; extern crate rustc_data_structures; extern crate rustc_driver; extern crate rustc_errors; extern crate rustc_hir; +extern crate rustc_incremental; extern crate rustc_interface; extern crate rustc_middle; extern crate rustc_mir; +extern crate rustc_serialize; extern crate rustc_session; extern crate rustc_span; extern crate rustc_symbol_mangling; @@ -33,7 +36,7 @@ use codegen_cx::CodegenCx; use rspirv::binary::Assemble; use rustc_ast::expand::allocator::AllocatorKind; use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule}; -use rustc_codegen_ssa::back::write::{CodegenContext, FatLTOInput, ModuleConfig}; +use rustc_codegen_ssa::back::write::{CodegenContext, FatLTOInput, ModuleConfig, OngoingCodegen}; use rustc_codegen_ssa::base::maybe_create_entry_wrapper; use rustc_codegen_ssa::mono_item::MonoItemExt; use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, WriteBackendMethods}; @@ -48,7 +51,8 @@ use rustc_middle::mir::mono::MonoItem; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{Instance, InstanceDef, TyCtxt}; -use rustc_session::config::{OptLevel, OutputFilenames, OutputType}; +use rustc_serialize::json; +use rustc_session::config::{self, OptLevel, OutputFilenames, OutputType}; use rustc_session::Session; use rustc_span::Symbol; use rustc_target::spec::Target; @@ -94,9 +98,9 @@ impl MetadataLoader for NoLlvmMetadataLoader { } #[derive(Clone)] -struct SsaBackend; +struct SpirvCodegenBackend; -impl CodegenBackend for SsaBackend { +impl CodegenBackend for SpirvCodegenBackend { fn metadata_loader(&self) -> Box { Box::new(NoLlvmMetadataLoader) } @@ -125,7 +129,7 @@ impl CodegenBackend for SsaBackend { need_metadata_module: bool, ) -> Box { Box::new(rustc_codegen_ssa::base::codegen_crate( - SsaBackend, + SpirvCodegenBackend, tcx, metadata, need_metadata_module, @@ -136,19 +140,19 @@ impl CodegenBackend for SsaBackend { &self, ongoing_codegen: Box, sess: &Session, - _dep_graph: &DepGraph, + dep_graph: &DepGraph, ) -> Result, ErrorReported> { - let (codegen_results, _work_products) = ongoing_codegen - .downcast::>() - .expect("Expected SpirvCodegenBackend's OngoingCodegen, found Box") + let (codegen_results, work_products) = ongoing_codegen + .downcast::>() + .expect("Expected OngoingCodegen, found Box") .join(sess); if sess.opts.debugging_opts.incremental_info { rustc_codegen_ssa::back::write::dump_incremental_data(&codegen_results); } - // sess.time("serialize_work_products", move || { - // rustc_incremental::save_work_product_index(sess, &dep_graph, work_products) - // }); + sess.time("serialize_work_products", move || { + rustc_incremental::save_work_product_index(sess, &dep_graph, work_products) + }); sess.compile_status()?; @@ -157,15 +161,38 @@ impl CodegenBackend for SsaBackend { fn link( &self, - _sess: &Session, + sess: &Session, codegen_results: Box, - _outputs: &OutputFilenames, + outputs: &OutputFilenames, ) -> Result<(), ErrorReported> { - let _codegen_results = codegen_results + let codegen_results = codegen_results .downcast::() .expect("Expected CodegenResults, found Box"); - // TODO: see rustc_codegen_llvm for example of implementation + if sess.opts.debugging_opts.no_link { + // FIXME: use a binary format to encode the `.rlink` file + let rlink_data = json::encode(&codegen_results).map_err(|err| { + sess.fatal(&format!("failed to encode rlink: {}", err)); + })?; + let rlink_file = outputs.with_extension(config::RLINK_EXT); + std::fs::write(&rlink_file, rlink_data).map_err(|err| { + sess.fatal(&format!( + "failed to write file {}: {}", + rlink_file.display(), + err + )); + })?; + return Ok(()); + } + + link::link( + sess, + &codegen_results, + outputs, + &codegen_results.crate_name.as_str(), + ); + + rustc_incremental::finalize_session_directory(sess, codegen_results.crate_hash); Ok(()) } @@ -190,7 +217,7 @@ fn slice_u8_to_u32(slice: &[u8]) -> &[u32] { } } -impl WriteBackendMethods for SsaBackend { +impl WriteBackendMethods for SpirvCodegenBackend { type Module = Vec; type TargetMachine = (); type ModuleBuffer = SpirvModuleBuffer; @@ -302,7 +329,7 @@ impl WriteBackendMethods for SsaBackend { } } -impl ExtraBackendMethods for SsaBackend { +impl ExtraBackendMethods for SpirvCodegenBackend { fn new_metadata(&self, _: TyCtxt<'_>, _: &str) -> Self::Module { todo!() } @@ -416,7 +443,7 @@ impl Drop for DumpModuleOnPanic<'_, '_, '_> { /// This is the entrypoint for a hot plugged rustc_codegen_spirv #[no_mangle] pub fn __rustc_codegen_backend() -> Box { - Box::new(SsaBackend) + Box::new(SpirvCodegenBackend) } // https://github.com/bjorn3/rustc_codegen_cranelift/blob/1b8df386aa72bc3dacb803f7d4deb4eadd63b56f/src/base.rs diff --git a/rustc_codegen_spirv/src/link.rs b/rustc_codegen_spirv/src/link.rs index 162e943410..f56c4151c5 100644 --- a/rustc_codegen_spirv/src/link.rs +++ b/rustc_codegen_spirv/src/link.rs @@ -1,18 +1,286 @@ use crate::things::{SpirvModuleBuffer, SpirvThinBuffer}; -use crate::SsaBackend; +use crate::SpirvCodegenBackend; use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule, ThinShared}; use rustc_codegen_ssa::back::write::CodegenContext; +use rustc_codegen_ssa::CodegenResults; use rustc_errors::FatalError; use rustc_middle::dep_graph::WorkProduct; -use rustc_session::config::Lto; +use rustc_middle::middle::cstore::NativeLib; +use rustc_middle::middle::dependency_format::Linkage; +use rustc_session::config::{CrateType, Lto, OutputFilenames, OutputType}; +use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename}; +use rustc_session::utils::NativeLibKind; +use rustc_session::Session; +use std::collections::HashSet; use std::ffi::CString; +use std::fs::File; +use std::io::Read; +use std::io::Write; +use std::path::{Path, PathBuf}; use std::sync::Arc; +use tar::{Archive, Builder}; + +pub fn link<'a>( + sess: &'a Session, + codegen_results: &CodegenResults, + outputs: &OutputFilenames, + crate_name: &str, +) { + let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata); + for &crate_type in sess.crate_types().iter() { + if (sess.opts.debugging_opts.no_codegen || !sess.opts.output_types.should_codegen()) + && !output_metadata + && crate_type == CrateType::Executable + { + continue; + } + + if invalid_output_for_target(sess, crate_type) { + panic!( + "invalid output type `{:?}` for target os `{}`", + crate_type, sess.opts.target_triple + ); + } + + for obj in codegen_results + .modules + .iter() + .filter_map(|m| m.object.as_ref()) + { + check_file_is_writeable(obj, sess); + } + + if outputs.outputs.should_codegen() { + let out_filename = out_filename(sess, crate_type, outputs, crate_name); + match crate_type { + CrateType::Rlib => { + link_rlib(codegen_results, &out_filename); + } + CrateType::Executable | CrateType::Cdylib => { + link_exe(sess, crate_type, &out_filename, codegen_results) + } + other => panic!("CrateType {:?} not supported yet", other), + } + } + } +} + +fn link_rlib(codegen_results: &CodegenResults, out_filename: &Path) { + let mut file_list = Vec::<&Path>::new(); + for obj in codegen_results + .modules + .iter() + .filter_map(|m| m.object.as_ref()) + { + file_list.push(obj); + } + for lib in codegen_results.crate_info.used_libraries.iter() { + match lib.kind { + NativeLibKind::StaticBundle => {} + NativeLibKind::StaticNoBundle + | NativeLibKind::Dylib + | NativeLibKind::Framework + | NativeLibKind::RawDylib + | NativeLibKind::Unspecified => continue, + } + if let Some(name) = lib.name { + panic!("Adding native library to rlib not supported yet: {}", name); + } + } + + // let metadata = &codegen_results.metadata.raw_data; + // file_list.push(metadata); + + create_archive(&file_list, out_filename); +} + +fn link_exe( + sess: &Session, + crate_type: CrateType, + out_filename: &Path, + codegen_results: &CodegenResults, +) { + let mut objects = Vec::new(); + let mut rlibs = Vec::new(); + for obj in codegen_results + .modules + .iter() + .filter_map(|m| m.object.as_ref()) + { + objects.push(obj.clone()); + } + + link_local_crate_native_libs_and_dependent_crate_libs( + &mut rlibs, + sess, + crate_type, + codegen_results, + ); + + do_link(&objects, &rlibs, out_filename); +} + +fn link_local_crate_native_libs_and_dependent_crate_libs<'a>( + rlibs: &mut Vec, + sess: &'a Session, + crate_type: CrateType, + codegen_results: &CodegenResults, +) { + if sess.opts.debugging_opts.link_native_libraries { + add_local_native_libraries(sess, codegen_results); + } + add_upstream_rust_crates(rlibs, codegen_results, crate_type); + if sess.opts.debugging_opts.link_native_libraries { + add_upstream_native_libraries(sess, codegen_results, crate_type); + } +} + +fn add_local_native_libraries(sess: &Session, codegen_results: &CodegenResults) { + let relevant_libs = codegen_results + .crate_info + .used_libraries + .iter() + .filter(|l| relevant_lib(sess, l)); + assert_eq!(relevant_libs.count(), 0); +} + +fn add_upstream_rust_crates( + rlibs: &mut Vec, + codegen_results: &CodegenResults, + crate_type: CrateType, +) { + let (_, data) = codegen_results + .crate_info + .dependency_formats + .iter() + .find(|(ty, _)| *ty == crate_type) + .expect("failed to find crate type in dependency format list"); + let deps = &codegen_results.crate_info.used_crates_dynamic; + for &(cnum, _) in deps.iter() { + let src = &codegen_results.crate_info.used_crate_source[&cnum]; + match data[cnum.as_usize() - 1] { + Linkage::NotLinked | Linkage::IncludedFromDylib => {} + Linkage::Static => rlibs.push(src.rlib.as_ref().unwrap().0.clone()), + //Linkage::Dynamic => rlibs.push(src.dylib.as_ref().unwrap().0.clone()), + Linkage::Dynamic => panic!("TODO: Linkage::Dynamic not supported yet"), + } + } +} + +fn add_upstream_native_libraries( + sess: &Session, + codegen_results: &CodegenResults, + crate_type: CrateType, +) { + let (_, data) = codegen_results + .crate_info + .dependency_formats + .iter() + .find(|(ty, _)| *ty == crate_type) + .expect("failed to find crate type in dependency format list"); + + let crates = &codegen_results.crate_info.used_crates_static; + for &(cnum, _) in crates { + for lib in codegen_results.crate_info.native_libraries[&cnum].iter() { + let name = match lib.name { + Some(l) => l, + None => continue, + }; + if !relevant_lib(sess, &lib) { + continue; + } + match lib.kind { + NativeLibKind::Dylib | NativeLibKind::Unspecified => { + panic!("TODO: dylib nativelibkind not supported yet: {}", name) + } + NativeLibKind::Framework => { + panic!("TODO: framework nativelibkind not supported yet: {}", name) + } + NativeLibKind::StaticNoBundle => { + if data[cnum.as_usize() - 1] == Linkage::Static { + panic!( + "TODO: staticnobundle nativelibkind not supported yet: {}", + name + ); + } + } + NativeLibKind::StaticBundle => {} + NativeLibKind::RawDylib => { + panic!("raw_dylib feature not yet implemented: {}", name); + } + } + } + } +} + +fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool { + match lib.cfg { + Some(ref cfg) => rustc_attr::cfg_matches(cfg, &sess.parse_sess, None), + None => true, + } +} + +fn create_archive(files: &[&Path], out_filename: &Path) { + let file = File::create(out_filename).unwrap(); + let mut builder = Builder::new(file); + let mut filenames = HashSet::new(); + for file in files { + assert!( + filenames.insert(file.file_name().unwrap()), + "Duplicate filename in archive: {:?}", + file.file_name().unwrap() + ); + builder + .append_path_with_name(file, file.file_name().unwrap()) + .unwrap(); + } + builder.into_inner().unwrap(); +} + +fn do_link(objects: &[PathBuf], rlibs: &[PathBuf], out_filename: &Path) { + let mut modules = Vec::new(); + for obj in objects { + let mut bytes = Vec::new(); + File::open(obj).unwrap().read_to_end(&mut bytes).unwrap(); + modules.push(load(&bytes)); + } + for rlib in rlibs { + for entry in Archive::new(File::open(rlib).unwrap()).entries().unwrap() { + let mut bytes = Vec::new(); + entry.unwrap().read_to_end(&mut bytes).unwrap(); + modules.push(load(&bytes)); + } + } + + let mut module_refs = modules.iter_mut().collect::>(); + + let result = rspirv_linker::link( + &mut module_refs, + &rspirv_linker::Options { + lib: false, + partial: false, + }, + ) + .unwrap(); + + use rspirv::binary::Assemble; + File::create(out_filename) + .unwrap() + .write_all(crate::slice_u32_to_u8(&result.assemble())) + .unwrap(); + + fn load(bytes: &[u8]) -> rspirv::dr::Module { + let mut loader = rspirv::dr::Loader::new(); + rspirv::binary::parse_bytes(&bytes, &mut loader).unwrap(); + loader.module() + } +} pub(crate) fn run_thin( - cgcx: &CodegenContext, + cgcx: &CodegenContext, modules: Vec<(String, SpirvThinBuffer)>, cached_modules: Vec<(SerializedModule, WorkProduct)>, -) -> Result<(Vec>, Vec), FatalError> { +) -> Result<(Vec>, Vec), FatalError> { if cgcx.opts.cg.linker_plugin_lto.enabled() { unreachable!("We should never reach this case if the LTO step is deferred to the linker"); }