mirror of
https://github.com/EmbarkStudios/rust-gpu.git
synced 2024-11-21 14:24:13 +00:00
Start work on integrating linker
This commit is contained in:
parent
f890ce0fcc
commit
c5dfee6e1e
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/target
|
73
rspirv-linker/Cargo.lock → Cargo.lock
generated
73
rspirv-linker/Cargo.lock → Cargo.lock
generated
@ -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",
|
||||
]
|
5
Cargo.toml
Normal file
5
Cargo.toml
Normal file
@ -0,0 +1,5 @@
|
||||
[workspace]
|
||||
members = [
|
||||
"rustc_codegen_spirv",
|
||||
"rspirv-linker",
|
||||
]
|
@ -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"
|
||||
|
||||
|
@ -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<rspirv::dr::Module> {
|
||||
pub fn link(inputs: &mut [&mut rspirv::dr::Module], opts: &Options) -> Result<rspirv::dr::Module> {
|
||||
// shift all the ids
|
||||
let mut bound = inputs[0].header.as_ref().unwrap().bound - 1;
|
||||
|
3
rustc_codegen_spirv/.gitignore
vendored
3
rustc_codegen_spirv/.gitignore
vendored
@ -1,3 +0,0 @@
|
||||
/target
|
||||
Cargo.lock
|
||||
*.spv
|
@ -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]
|
||||
|
@ -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
|
||||
|
@ -1 +1,2 @@
|
||||
/target/
|
||||
/Cargo.lock
|
||||
|
@ -4,4 +4,9 @@ version = "0.1.0"
|
||||
authors = ["Ashley Hauck <ashley.hauck@embark-studios.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
|
||||
[workspace]
|
||||
|
@ -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::<u32>(),
|
||||
)
|
||||
};
|
||||
File::create(path)
|
||||
.unwrap()
|
||||
.write_all(spirv_module_u8)
|
||||
.write_all(crate::slice_u32_to_u8(&spirv_module))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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<MetadataLoaderDyn> {
|
||||
Box::new(NoLlvmMetadataLoader)
|
||||
}
|
||||
@ -125,7 +129,7 @@ impl CodegenBackend for SsaBackend {
|
||||
need_metadata_module: bool,
|
||||
) -> Box<dyn Any> {
|
||||
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<dyn Any>,
|
||||
sess: &Session,
|
||||
_dep_graph: &DepGraph,
|
||||
dep_graph: &DepGraph,
|
||||
) -> Result<Box<dyn Any>, ErrorReported> {
|
||||
let (codegen_results, _work_products) = ongoing_codegen
|
||||
.downcast::<rustc_codegen_ssa::back::write::OngoingCodegen<SsaBackend>>()
|
||||
.expect("Expected SpirvCodegenBackend's OngoingCodegen, found Box<Any>")
|
||||
let (codegen_results, work_products) = ongoing_codegen
|
||||
.downcast::<OngoingCodegen<SpirvCodegenBackend>>()
|
||||
.expect("Expected OngoingCodegen, found Box<Any>")
|
||||
.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<dyn Any>,
|
||||
_outputs: &OutputFilenames,
|
||||
outputs: &OutputFilenames,
|
||||
) -> Result<(), ErrorReported> {
|
||||
let _codegen_results = codegen_results
|
||||
let codegen_results = codegen_results
|
||||
.downcast::<CodegenResults>()
|
||||
.expect("Expected CodegenResults, found Box<Any>");
|
||||
|
||||
// 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<u32>;
|
||||
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<dyn CodegenBackend> {
|
||||
Box::new(SsaBackend)
|
||||
Box::new(SpirvCodegenBackend)
|
||||
}
|
||||
|
||||
// https://github.com/bjorn3/rustc_codegen_cranelift/blob/1b8df386aa72bc3dacb803f7d4deb4eadd63b56f/src/base.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<PathBuf>,
|
||||
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<PathBuf>,
|
||||
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::<Vec<_>>();
|
||||
|
||||
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<SsaBackend>,
|
||||
cgcx: &CodegenContext<SpirvCodegenBackend>,
|
||||
modules: Vec<(String, SpirvThinBuffer)>,
|
||||
cached_modules: Vec<(SerializedModule<SpirvModuleBuffer>, WorkProduct)>,
|
||||
) -> Result<(Vec<LtoModuleCodegen<SsaBackend>>, Vec<WorkProduct>), FatalError> {
|
||||
) -> Result<(Vec<LtoModuleCodegen<SpirvCodegenBackend>>, Vec<WorkProduct>), 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");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user