mirror of
https://github.com/EmbarkStudios/rust-gpu.git
synced 2024-10-30 05:52:39 +00:00
global_asm! start
This commit is contained in:
parent
8a68551a06
commit
c0213eb229
@ -29,7 +29,8 @@ use-compiled-tools = ["spirv-tools/use-compiled-tools"]
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
bimap = "0.6"
|
bimap = "0.6"
|
||||||
indexmap = "1.6.0"
|
indexmap = "1.6.0"
|
||||||
rspirv = { git = "https://github.com/gfx-rs/rspirv.git", rev = "7111e6c5a8bb43563d280825fa65623032ee052d" }
|
#rspirv = { git = "https://github.com/gfx-rs/rspirv.git", rev = "7111e6c5a8bb43563d280825fa65623032ee052d" }
|
||||||
|
rspirv = { path = "c:/users/jasper/embark/rspirv/rspirv" }
|
||||||
rustc-demangle = "0.1.18"
|
rustc-demangle = "0.1.18"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
@ -2,7 +2,7 @@ mod builder_methods;
|
|||||||
mod ext_inst;
|
mod ext_inst;
|
||||||
mod intrinsics;
|
mod intrinsics;
|
||||||
pub mod libm_intrinsics;
|
pub mod libm_intrinsics;
|
||||||
mod spirv_asm;
|
pub mod spirv_asm;
|
||||||
|
|
||||||
pub use ext_inst::ExtInst;
|
pub use ext_inst::ExtInst;
|
||||||
use rustc_span::DUMMY_SP;
|
use rustc_span::DUMMY_SP;
|
||||||
|
@ -98,7 +98,7 @@ impl<'a, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'tcx> {
|
|||||||
tokens.push(vec![]);
|
tokens.push(vec![]);
|
||||||
}
|
}
|
||||||
let mut chars = line.chars();
|
let mut chars = line.chars();
|
||||||
while let Some(token) = self.lex_word(&mut chars) {
|
while let Some(token) = InlineAsmCx::Local(self).lex_word(&mut chars) {
|
||||||
tokens.last_mut().unwrap().push(token);
|
tokens.last_mut().unwrap().push(token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -132,25 +132,35 @@ impl<'a, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut id_map = HashMap::new();
|
let mut id_map = HashMap::new();
|
||||||
let mut id_to_type_map = HashMap::new();
|
let global_id_map = self.cx.global_asm_id_map.borrow();
|
||||||
|
for (k, v) in global_id_map.iter() {
|
||||||
|
id_map.insert(k.as_str(), *v);
|
||||||
|
}
|
||||||
|
let mut id_to_type_map = self.cx.global_asm_id_to_type_map.borrow().clone();
|
||||||
|
|
||||||
for operand in operands {
|
for operand in operands {
|
||||||
if let InlineAsmOperandRef::In { reg: _, value } = operand {
|
if let InlineAsmOperandRef::In { reg: _, value } = operand {
|
||||||
let value = value.immediate();
|
let value = value.immediate();
|
||||||
id_to_type_map.insert(value.def(self), value.ty);
|
id_to_type_map.insert(value.def(self), value.ty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for line in tokens {
|
for line in tokens {
|
||||||
self.codegen_asm(&mut id_map, &mut id_to_type_map, line.into_iter());
|
InlineAsmCx::Local(self).codegen_asm(
|
||||||
|
&mut id_map,
|
||||||
|
&mut id_to_type_map,
|
||||||
|
line.into_iter(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum TypeofKind {
|
pub enum TypeofKind {
|
||||||
Plain,
|
Plain,
|
||||||
Dereference,
|
Dereference,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Token<'a, 'cx, 'tcx> {
|
pub enum Token<'a, 'cx, 'tcx> {
|
||||||
Word(&'a str),
|
Word(&'a str),
|
||||||
String(String),
|
String(String),
|
||||||
Placeholder(&'a InlineAsmOperandRef<'tcx, Builder<'cx, 'tcx>>, Span),
|
Placeholder(&'a InlineAsmOperandRef<'tcx, Builder<'cx, 'tcx>>, Span),
|
||||||
@ -166,8 +176,56 @@ enum OutRegister<'a> {
|
|||||||
Place(PlaceRef<'a, SpirvValue>),
|
Place(PlaceRef<'a, SpirvValue>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'cx, 'tcx> Builder<'cx, 'tcx> {
|
pub enum InlineAsmCx<'a, 'cx, 'tcx> {
|
||||||
fn lex_word<'a>(&self, line: &mut std::str::Chars<'a>) -> Option<Token<'a, 'cx, 'tcx>> {
|
Global(&'cx CodegenCx<'tcx>, Span),
|
||||||
|
Local(&'a mut Builder<'cx, 'tcx>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'cx, 'tcx> std::ops::Deref for InlineAsmCx<'_, 'cx, 'tcx> {
|
||||||
|
type Target = &'cx CodegenCx<'tcx>;
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
match self {
|
||||||
|
Self::Global(cx, _) | Self::Local(Builder { cx, .. }) => cx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InlineAsmCx<'_, '_, '_> {
|
||||||
|
fn span(&self) -> Span {
|
||||||
|
match self {
|
||||||
|
&Self::Global(_, span) => span,
|
||||||
|
Self::Local(bx) => bx.span(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn err(&self, msg: &str) {
|
||||||
|
self.tcx.sess.span_err(self.span(), msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn emit(&self) -> std::cell::RefMut<'_, rspirv::dr::Builder> {
|
||||||
|
match self {
|
||||||
|
Self::Global(cx, _) => cx.emit_global(),
|
||||||
|
Self::Local(bx) => bx.emit(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn emit_append(&self, inst: dr::Instruction){
|
||||||
|
match self {
|
||||||
|
Self::Global(cx, _) => cx.emit_global().insert_types_global_values(dr::InsertPoint::End, inst),
|
||||||
|
Self::Local(bx) => bx.emit().insert_into_block(dr::InsertPoint::End, inst).unwrap(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn emit_global(&self, inst: dr::Instruction){
|
||||||
|
match self {
|
||||||
|
Self::Global(cx, _) => cx.emit_global().insert_types_global_values(dr::InsertPoint::End, inst),
|
||||||
|
Self::Local(bx) => bx.emit_global().insert_types_global_values(dr::InsertPoint::End, inst),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'cx, 'tcx> InlineAsmCx<'_, 'cx, 'tcx> {
|
||||||
|
pub fn lex_word<'a>(&self, line: &mut std::str::Chars<'a>) -> Option<Token<'a, 'cx, 'tcx>> {
|
||||||
loop {
|
loop {
|
||||||
let start = line.as_str();
|
let start = line.as_str();
|
||||||
match line.next()? {
|
match line.next()? {
|
||||||
@ -228,6 +286,8 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
|
|||||||
|
|
||||||
fn insert_inst(&mut self, id_map: &mut HashMap<&str, Word>, inst: dr::Instruction) {
|
fn insert_inst(&mut self, id_map: &mut HashMap<&str, Word>, inst: dr::Instruction) {
|
||||||
// Types declared must be registered in our type system.
|
// Types declared must be registered in our type system.
|
||||||
|
println!("{:?}", &inst);
|
||||||
|
|
||||||
let new_result_id = match inst.class.opcode {
|
let new_result_id = match inst.class.opcode {
|
||||||
Op::TypeVoid => SpirvType::Void.def(self.span(), self),
|
Op::TypeVoid => SpirvType::Void.def(self.span(), self),
|
||||||
Op::TypeBool => SpirvType::Bool.def(self.span(), self),
|
Op::TypeBool => SpirvType::Bool.def(self.span(), self),
|
||||||
@ -255,15 +315,34 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
|
|||||||
Op::TypeArray => {
|
Op::TypeArray => {
|
||||||
self.err("OpTypeArray in asm! is not supported yet");
|
self.err("OpTypeArray in asm! is not supported yet");
|
||||||
return;
|
return;
|
||||||
}
|
},
|
||||||
|
Op::TypeRuntimeArray => SpirvType::RuntimeArray {
|
||||||
|
element: inst.operands[0].unwrap_id_ref()
|
||||||
|
}.def(self.span(), self),
|
||||||
|
Op::TypePointer => SpirvType::Pointer {
|
||||||
|
storage_class: inst.operands[0].unwrap_storage_class(),
|
||||||
|
pointee: inst.operands[1].unwrap_id_ref(),
|
||||||
|
}.def(self.span(), self),
|
||||||
|
Op::TypeImage => SpirvType::Image {
|
||||||
|
sampled_type: inst.operands[0].unwrap_id_ref(),
|
||||||
|
dim: inst.operands[1].unwrap_dim(),
|
||||||
|
depth: inst.operands[2].unwrap_literal_int32(),
|
||||||
|
arrayed: inst.operands[3].unwrap_literal_int32(),
|
||||||
|
multisampled: inst.operands[4].unwrap_literal_int32(),
|
||||||
|
sampled: inst.operands[5].unwrap_literal_int32(),
|
||||||
|
image_format: inst.operands[6].unwrap_image_format(),
|
||||||
|
access_qualifier: None,
|
||||||
|
}.def(self.span(), self),
|
||||||
Op::TypeSampledImage => SpirvType::SampledImage {
|
Op::TypeSampledImage => SpirvType::SampledImage {
|
||||||
image_type: inst.operands[0].unwrap_id_ref(),
|
image_type: inst.operands[0].unwrap_id_ref(),
|
||||||
}
|
}
|
||||||
.def(self.span(), self),
|
.def(self.span(), self),
|
||||||
|
Op::Variable => {
|
||||||
|
self.emit_global(inst);
|
||||||
|
return;
|
||||||
|
},
|
||||||
_ => {
|
_ => {
|
||||||
self.emit()
|
self.emit_append(inst);
|
||||||
.insert_into_block(dr::InsertPoint::End, inst)
|
|
||||||
.unwrap();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -274,7 +353,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn codegen_asm<'a>(
|
pub fn codegen_asm<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
id_map: &mut HashMap<&'a str, Word>,
|
id_map: &mut HashMap<&'a str, Word>,
|
||||||
id_to_type_map: &mut HashMap<Word, Word>,
|
id_to_type_map: &mut HashMap<Word, Word>,
|
||||||
@ -358,13 +437,12 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
|
|||||||
}
|
}
|
||||||
self.insert_inst(id_map, instruction);
|
self.insert_inst(id_map, instruction);
|
||||||
if let Some(OutRegister::Place(place)) = out_register {
|
if let Some(OutRegister::Place(place)) = out_register {
|
||||||
|
let place = match self {
|
||||||
|
Self::Global(..) => unreachable!(),
|
||||||
|
Self::Local(bx) => place.llval.def(bx),
|
||||||
|
};
|
||||||
self.emit()
|
self.emit()
|
||||||
.store(
|
.store(place, result_id.unwrap(), None, std::iter::empty())
|
||||||
place.llval.def(self),
|
|
||||||
result_id.unwrap(),
|
|
||||||
None,
|
|
||||||
std::iter::empty(),
|
|
||||||
)
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -755,7 +833,10 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
|
|||||||
Token::Placeholder(hole, span) => match hole {
|
Token::Placeholder(hole, span) => match hole {
|
||||||
InlineAsmOperandRef::In { reg, value } => {
|
InlineAsmOperandRef::In { reg, value } => {
|
||||||
self.check_reg(span, reg);
|
self.check_reg(span, reg);
|
||||||
Some(value.immediate().def(self))
|
match self {
|
||||||
|
Self::Global(..) => unreachable!(),
|
||||||
|
Self::Local(bx) => Some(value.immediate().def(bx)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
InlineAsmOperandRef::Out {
|
InlineAsmOperandRef::Out {
|
||||||
reg,
|
reg,
|
||||||
@ -775,7 +856,10 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
|
|||||||
out_place: _,
|
out_place: _,
|
||||||
} => {
|
} => {
|
||||||
self.check_reg(span, reg);
|
self.check_reg(span, reg);
|
||||||
Some(in_value.immediate().def(self))
|
match self {
|
||||||
|
Self::Global(..) => unreachable!(),
|
||||||
|
Self::Local(bx) => Some(in_value.immediate().def(bx)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
InlineAsmOperandRef::Const { string: _ } => {
|
InlineAsmOperandRef::Const { string: _ } => {
|
||||||
self.tcx
|
self.tcx
|
||||||
@ -890,6 +974,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
|
|||||||
_ => return Err("expected number literal in OpConstant".to_string()),
|
_ => return Err("expected number literal in OpConstant".to_string()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
println!("{} {}", ty, word);
|
||||||
match parse(self.lookup_type(ty), word) {
|
match parse(self.lookup_type(ty), word) {
|
||||||
Ok(op) => inst.operands.push(op),
|
Ok(op) => inst.operands.push(op),
|
||||||
Err(err) => self.err(&err),
|
Err(err) => self.err(&err),
|
||||||
|
@ -69,6 +69,9 @@ pub struct CodegenCx<'tcx> {
|
|||||||
/// Some runtimes (e.g. intel-compute-runtime) disallow atomics on i8 and i16, even though it's allowed by the spec.
|
/// Some runtimes (e.g. intel-compute-runtime) disallow atomics on i8 and i16, even though it's allowed by the spec.
|
||||||
/// This enables/disables them.
|
/// This enables/disables them.
|
||||||
pub i8_i16_atomics_allowed: bool,
|
pub i8_i16_atomics_allowed: bool,
|
||||||
|
|
||||||
|
pub global_asm_id_map: RefCell<HashMap<String, Word>>,
|
||||||
|
pub global_asm_id_to_type_map: RefCell<HashMap<Word, Word>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> CodegenCx<'tcx> {
|
impl<'tcx> CodegenCx<'tcx> {
|
||||||
@ -121,6 +124,8 @@ impl<'tcx> CodegenCx<'tcx> {
|
|||||||
panic_fn_id: Default::default(),
|
panic_fn_id: Default::default(),
|
||||||
panic_bounds_check_fn_id: Default::default(),
|
panic_bounds_check_fn_id: Default::default(),
|
||||||
i8_i16_atomics_allowed: false,
|
i8_i16_atomics_allowed: false,
|
||||||
|
global_asm_id_map: Default::default(),
|
||||||
|
global_asm_id_to_type_map: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -402,8 +407,52 @@ impl<'tcx> CoverageInfoMethods for CodegenCx<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use crate::builder::spirv_asm::InlineAsmCx;
|
||||||
|
|
||||||
impl<'tcx> AsmMethods for CodegenCx<'tcx> {
|
impl<'tcx> AsmMethods for CodegenCx<'tcx> {
|
||||||
fn codegen_global_asm(&self, _ga: &GlobalAsm) {
|
fn codegen_global_asm(&self, ga: &GlobalAsm) {
|
||||||
todo!()
|
use rustc_span::DUMMY_SP;
|
||||||
|
|
||||||
|
// vec of lines, and each line is vec of tokens
|
||||||
|
let mut tokens = vec![vec![]];
|
||||||
|
|
||||||
|
let asm = ga.asm.as_str().to_string();
|
||||||
|
|
||||||
|
let lines = asm.split('\n').map(|line| {
|
||||||
|
let l = line.len();
|
||||||
|
if l > 0 && line.as_bytes()[l - 1] == b'\r' {
|
||||||
|
&line[0..l - 1]
|
||||||
|
} else {
|
||||||
|
line
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
for (index, line) in lines.enumerate() {
|
||||||
|
if index != 0 {
|
||||||
|
// There was a newline, add a new line.
|
||||||
|
tokens.push(vec![]);
|
||||||
|
}
|
||||||
|
let mut chars = line.chars();
|
||||||
|
|
||||||
|
// passing around DUMMY_SP in here now, because it's unclear how to create a Span from a Symbol
|
||||||
|
while let Some(token) = InlineAsmCx::Global(self, DUMMY_SP).lex_word(&mut chars) {
|
||||||
|
tokens.last_mut().unwrap().push(token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut id_map = HashMap::new();
|
||||||
|
|
||||||
|
for line in tokens {
|
||||||
|
// passing around DUMMY_SP in here now, because it's unclear how to create a Span from a Symbol
|
||||||
|
InlineAsmCx::Global(self, DUMMY_SP).codegen_asm(
|
||||||
|
&mut id_map,
|
||||||
|
&mut self.global_asm_id_to_type_map.borrow_mut(),
|
||||||
|
line.into_iter(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (k, v) in id_map {
|
||||||
|
self.global_asm_id_map.borrow_mut().insert(k.to_owned(), v);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user