mirror of
https://github.com/EmbarkStudios/rust-gpu.git
synced 2024-11-21 22:34:34 +00:00
Start emitting spirv modules
This commit is contained in:
parent
cf71e44bb6
commit
9ab212f93c
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
/target
|
/target
|
||||||
Cargo.lock
|
Cargo.lock
|
||||||
|
*.spv
|
||||||
|
@ -10,3 +10,5 @@ edition = "2018"
|
|||||||
crate-type = ["dylib"]
|
crate-type = ["dylib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
rspirv = "0.6"
|
||||||
|
spirv_headers = "1.4"
|
||||||
|
@ -1 +0,0 @@
|
|||||||
This has been "compiled" successfully.
|
|
106
src/lib.rs
106
src/lib.rs
@ -1,4 +1,5 @@
|
|||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
|
#![feature(or_insert_with_key)]
|
||||||
|
|
||||||
extern crate rustc_codegen_ssa;
|
extern crate rustc_codegen_ssa;
|
||||||
extern crate rustc_errors;
|
extern crate rustc_errors;
|
||||||
@ -19,18 +20,17 @@ use rustc_data_structures::sync::MetadataRef;
|
|||||||
use rustc_errors::ErrorReported;
|
use rustc_errors::ErrorReported;
|
||||||
use rustc_middle::dep_graph::DepGraph;
|
use rustc_middle::dep_graph::DepGraph;
|
||||||
use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoader, MetadataLoaderDyn};
|
use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoader, MetadataLoaderDyn};
|
||||||
|
use rustc_middle::mir::mono::MonoItem;
|
||||||
use rustc_middle::ty::query::Providers;
|
use rustc_middle::ty::query::Providers;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_session::config::OutputFilenames;
|
use rustc_session::config::OutputFilenames;
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::symbol::Symbol;
|
|
||||||
use rustc_target::spec::Target;
|
use rustc_target::spec::Target;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use rustc_middle::mir::mono::{Linkage as RLinkage, MonoItem, Visibility};
|
mod spirv_ctx;
|
||||||
use rustc_middle::mir::Rvalue;
|
mod trans;
|
||||||
use rustc_middle::mir::StatementKind;
|
|
||||||
|
|
||||||
pub struct NoLlvmMetadataLoader;
|
pub struct NoLlvmMetadataLoader;
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ impl CodegenBackend for TheBackend {
|
|||||||
rustc_symbol_mangling::provide(providers);
|
rustc_symbol_mangling::provide(providers);
|
||||||
|
|
||||||
// jb-todo: target_features_whitelist is old name for supported_target_features
|
// jb-todo: target_features_whitelist is old name for supported_target_features
|
||||||
providers.target_features_whitelist = |tcx, _cnum| {
|
providers.supported_target_features = |_tcx, _cnum| {
|
||||||
Default::default() // Just a dummy
|
Default::default() // Just a dummy
|
||||||
};
|
};
|
||||||
providers.is_reachable_non_generic = |_tcx, _defid| true;
|
providers.is_reachable_non_generic = |_tcx, _defid| true;
|
||||||
@ -89,68 +89,25 @@ impl CodegenBackend for TheBackend {
|
|||||||
|
|
||||||
dbg!(cgus.len());
|
dbg!(cgus.len());
|
||||||
|
|
||||||
|
let mut translator = trans::Translator::new(tcx);
|
||||||
|
|
||||||
cgus.iter().for_each(|cgu| {
|
cgus.iter().for_each(|cgu| {
|
||||||
dbg!(cgu.name());
|
dbg!(cgu.name());
|
||||||
|
|
||||||
let cgu = tcx.codegen_unit(cgu.name());
|
let cgu = tcx.codegen_unit(cgu.name());
|
||||||
let mono_items = cgu.items_in_deterministic_order(tcx);
|
let mono_items = cgu.items_in_deterministic_order(tcx);
|
||||||
|
|
||||||
for (mono_item, (linkage, visibility)) in mono_items {
|
for (mono_item, (_linkage, _visibility)) in mono_items {
|
||||||
match mono_item {
|
match mono_item {
|
||||||
MonoItem::Fn(instance) => {
|
MonoItem::Fn(instance) => translator.trans_fn(instance),
|
||||||
{
|
thing => println!("Unknown MonoItem: {:?}", thing),
|
||||||
let mut mir = ::std::io::Cursor::new(Vec::new());
|
|
||||||
|
|
||||||
crate::rustc_mir::util::write_mir_pretty(
|
|
||||||
tcx,
|
|
||||||
Some(instance.def_id()),
|
|
||||||
&mut mir,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let s = String::from_utf8(mir.into_inner()).unwrap();
|
|
||||||
|
|
||||||
println!("{}", s);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mir = tcx.instance_mir(instance.def);
|
|
||||||
for (bb, bb_data) in mir.basic_blocks().iter_enumerated() {
|
|
||||||
for stmt in &bb_data.statements {
|
|
||||||
match &stmt.kind {
|
|
||||||
StatementKind::Assign(to_place_and_rval) => {
|
|
||||||
let place = to_place_and_rval.0; // jb-todo: iterate though place.projection & build OpAccessChain from it? see trans_place in cranelift
|
|
||||||
|
|
||||||
dbg!(&place);
|
|
||||||
for elem in place.projection {
|
|
||||||
match elem {
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dbg!(&to_place_and_rval.1);
|
|
||||||
match &to_place_and_rval.1 {
|
|
||||||
Rvalue::Use(operand) => {
|
|
||||||
//let val = trans_operand(fx, operand);
|
|
||||||
//lval.write_cvalue(fx, val);
|
|
||||||
dbg!(operand);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
//let lval = trans_place(fx, to_place_and_rval.0);
|
|
||||||
//dbg!(lval);
|
|
||||||
//println!("Assign");
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Box::new(tcx.crate_name(LOCAL_CRATE) as Symbol)
|
let module = translator.assemble();
|
||||||
|
|
||||||
|
Box::new(module)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn join_codegen(
|
fn join_codegen(
|
||||||
@ -159,10 +116,11 @@ impl CodegenBackend for TheBackend {
|
|||||||
_sess: &Session,
|
_sess: &Session,
|
||||||
_dep_graph: &DepGraph,
|
_dep_graph: &DepGraph,
|
||||||
) -> Result<Box<dyn Any>, ErrorReported> {
|
) -> Result<Box<dyn Any>, ErrorReported> {
|
||||||
let crate_name = ongoing_codegen
|
Ok(ongoing_codegen)
|
||||||
.downcast::<Symbol>()
|
// let crate_name = ongoing_codegen
|
||||||
.expect("in join_codegen: ongoing_codegen is not a Symbol");
|
// .downcast::<Symbol>()
|
||||||
Ok(crate_name)
|
// .expect("in join_codegen: ongoing_codegen is not a Symbol");
|
||||||
|
// Ok(crate_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn link(
|
fn link(
|
||||||
@ -171,18 +129,29 @@ impl CodegenBackend for TheBackend {
|
|||||||
codegen_results: Box<dyn Any>,
|
codegen_results: Box<dyn Any>,
|
||||||
outputs: &OutputFilenames,
|
outputs: &OutputFilenames,
|
||||||
) -> Result<(), ErrorReported> {
|
) -> Result<(), ErrorReported> {
|
||||||
use rustc_session::{config::CrateType, output::out_filename};
|
use rustc_session::config::{CrateType, OutputType};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
let crate_name = codegen_results
|
let codegen_bytes = codegen_results
|
||||||
.downcast::<Symbol>()
|
.downcast::<Vec<u32>>()
|
||||||
.expect("in link: codegen_results is not a Symbol");
|
.expect("in link: codegen_results is not a Vec<u32>");
|
||||||
for &crate_type in sess.opts.crate_types.iter() {
|
for &crate_type in sess.opts.crate_types.iter() {
|
||||||
if crate_type != CrateType::Rlib {
|
if crate_type != CrateType::Rlib {
|
||||||
sess.fatal(&format!("Crate type is {:?}", crate_type));
|
sess.fatal(&format!("Crate type is {:?}", crate_type));
|
||||||
}
|
}
|
||||||
let output_name = out_filename(sess, crate_type, &outputs, &*crate_name.as_str());
|
let mut output_name = outputs.path(OutputType::Exe);
|
||||||
let mut out_file = ::std::fs::File::create(output_name).unwrap();
|
output_name.set_extension("spv");
|
||||||
write!(out_file, "This has been \"compiled\" successfully.").unwrap();
|
let mut out_file =
|
||||||
|
::std::fs::File::create(output_name).expect("Unable to create output file");
|
||||||
|
// Note: endianness doesn't matter, readers deduce endianness from magic header.
|
||||||
|
let bytes_u8: &[u8] = unsafe {
|
||||||
|
std::slice::from_raw_parts(
|
||||||
|
codegen_bytes.as_ptr() as *const u8,
|
||||||
|
codegen_bytes.len() * std::mem::size_of::<u32>(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
out_file
|
||||||
|
.write_all(bytes_u8)
|
||||||
|
.expect("Unable to write output file");
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -194,5 +163,4 @@ pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
|
|||||||
Box::new(TheBackend)
|
Box::new(TheBackend)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://github.com/bjorn3/rustc_codegen_cranelift/blob/1b8df386aa72bc3dacb803f7d4deb4eadd63b56f/src/base.rs
|
||||||
// https://github.com/bjorn3/rustc_codegen_cranelift/blob/1b8df386aa72bc3dacb803f7d4deb4eadd63b56f/src/base.rs
|
|
||||||
|
75
src/spirv_ctx.rs
Normal file
75
src/spirv_ctx.rs
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
use rspirv::dr::Builder;
|
||||||
|
use spirv_headers::{AddressingModel, MemoryModel, Word};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
macro_rules! impl_cache {
|
||||||
|
($name:ident) => {
|
||||||
|
pub fn $name(&mut self) -> Word {
|
||||||
|
match self.cache.$name {
|
||||||
|
Some(value) => value,
|
||||||
|
None => {
|
||||||
|
let value = self.builder.$name();
|
||||||
|
self.cache.$name = Some(value);
|
||||||
|
value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SpirvContext {
|
||||||
|
pub builder: Builder,
|
||||||
|
cache: Cache,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct Cache {
|
||||||
|
type_void: Option<Word>,
|
||||||
|
type_bool: Option<Word>,
|
||||||
|
type_int: HashMap<(u32, u32), Word>,
|
||||||
|
type_float: HashMap<u32, Word>,
|
||||||
|
type_function: HashMap<(Word, Vec<Word>), Word>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SpirvContext {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let mut builder = Builder::new();
|
||||||
|
builder.memory_model(AddressingModel::Logical, MemoryModel::GLSL450);
|
||||||
|
SpirvContext {
|
||||||
|
builder,
|
||||||
|
cache: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_cache! {type_void}
|
||||||
|
impl_cache! {type_bool}
|
||||||
|
|
||||||
|
pub fn type_int(&mut self, width: u32, signedness: u32) -> Word {
|
||||||
|
let builder = &mut self.builder;
|
||||||
|
*self
|
||||||
|
.cache
|
||||||
|
.type_int
|
||||||
|
.entry((width, signedness))
|
||||||
|
.or_insert_with(|| builder.type_int(width, signedness))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn type_float(&mut self, width: u32) -> Word {
|
||||||
|
let builder = &mut self.builder;
|
||||||
|
*self
|
||||||
|
.cache
|
||||||
|
.type_float
|
||||||
|
.entry(width)
|
||||||
|
.or_insert_with(|| builder.type_float(width))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn type_function(&mut self, return_type: Word, parameter_types: Vec<Word>) -> Word {
|
||||||
|
let builder = &mut self.builder;
|
||||||
|
*self
|
||||||
|
.cache
|
||||||
|
.type_function
|
||||||
|
.entry((return_type, parameter_types))
|
||||||
|
.or_insert_with_key(|(return_type, parameter_types)| {
|
||||||
|
builder.type_function(*return_type, parameter_types)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
94
src/trans.rs
Normal file
94
src/trans.rs
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
use crate::spirv_ctx::SpirvContext;
|
||||||
|
use rspirv::binary::Assemble;
|
||||||
|
use rustc_middle::mir::{Rvalue, Statement, StatementKind};
|
||||||
|
use rustc_middle::ty::TyCtxt;
|
||||||
|
use spirv_headers::FunctionControl;
|
||||||
|
|
||||||
|
pub struct Translator<'tcx> {
|
||||||
|
spirv: SpirvContext,
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Translator<'tcx> {
|
||||||
|
pub fn new(tcx: TyCtxt<'tcx>) -> Self {
|
||||||
|
let spirv = SpirvContext::new();
|
||||||
|
Self { spirv, tcx }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn assemble(self) -> Vec<u32> {
|
||||||
|
self.spirv.builder.module().assemble()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn trans_fn(&mut self, instance: rustc_middle::ty::Instance<'tcx>) {
|
||||||
|
{
|
||||||
|
let mut mir = ::std::io::Cursor::new(Vec::new());
|
||||||
|
|
||||||
|
crate::rustc_mir::util::write_mir_pretty(self.tcx, Some(instance.def_id()), &mut mir)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let s = String::from_utf8(mir.into_inner()).unwrap();
|
||||||
|
|
||||||
|
println!("{}", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
let void = self.spirv.type_void();
|
||||||
|
let void_function = self.spirv.type_function(void, vec![void]);
|
||||||
|
let function_id = None;
|
||||||
|
let control = FunctionControl::NONE;
|
||||||
|
let _ = self
|
||||||
|
.spirv
|
||||||
|
.builder
|
||||||
|
.begin_function(void, function_id, control, void_function)
|
||||||
|
.unwrap();
|
||||||
|
let mir = self.tcx.instance_mir(instance.def);
|
||||||
|
for (_bb, bb_data) in mir.basic_blocks().iter_enumerated() {
|
||||||
|
self.spirv.builder.begin_block(None).unwrap();
|
||||||
|
for stmt in &bb_data.statements {
|
||||||
|
self.trans_stmt(stmt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.spirv.builder.end_function().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn trans_stmt(&self, stmt: &Statement) {
|
||||||
|
match &stmt.kind {
|
||||||
|
StatementKind::Assign(place_and_rval) => {
|
||||||
|
// can't destructure this since it's a Box<(place, rvalue)>
|
||||||
|
let place = place_and_rval.0;
|
||||||
|
let rvalue = &place_and_rval.1;
|
||||||
|
|
||||||
|
dbg!(&place);
|
||||||
|
for elem in place.projection {
|
||||||
|
match elem {
|
||||||
|
thing => println!("Unknown projection: {:?}", thing),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dbg!(&rvalue);
|
||||||
|
match &rvalue {
|
||||||
|
Rvalue::Use(operand) => {
|
||||||
|
//let val = trans_operand(fx, operand);
|
||||||
|
//lval.write_cvalue(fx, val);
|
||||||
|
dbg!(operand);
|
||||||
|
}
|
||||||
|
thing => println!("Unknown place: {:?}", thing),
|
||||||
|
}
|
||||||
|
//let lval = trans_place(fx, to_place_and_rval.0);
|
||||||
|
//dbg!(lval);
|
||||||
|
//println!("Assign");
|
||||||
|
}
|
||||||
|
thing => println!("Unknown statement: {:?}", thing),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn trans_expr(&self, expr: Rvalue<'tcx>) {
|
||||||
|
match &expr {
|
||||||
|
Rvalue::Use(operand) => {
|
||||||
|
//let val = trans_operand(fx, operand);
|
||||||
|
//lval.write_cvalue(fx, val);
|
||||||
|
dbg!(operand);
|
||||||
|
}
|
||||||
|
thing => println!("Unknown place: {:?}", thing),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -34,7 +34,5 @@ struct Jasper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn jasper() {
|
pub fn jasper() {
|
||||||
let _ktest = Jasper {
|
let _ktest = Jasper { data: 666666 };
|
||||||
data: 666666
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user