Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement partial OpLine support #193

Merged
merged 3 commits into from
May 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions autogen/src/dr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -854,22 +854,34 @@ pub fn gen_dr_builder_debug(grammar: &structs::Grammar) -> TokenStream {
let elements = grammar
.instructions
.iter()
.filter(|inst| inst.class == Some(structs::Class::Debug) && inst.opname != "OpString")
.filter(|inst| {
inst.class == Some(structs::Class::Debug)
&& !matches!(inst.opname.as_str(), "OpString" | "OpLine" | "OpNoLine")
})
.map(|inst| {
let params = get_param_list(&inst.operands, false, kinds);
let extras = get_push_extras(&inst.operands, kinds, quote! { inst.operands });
let opcode = as_ident(&inst.opname[2..]);
let comment = format!("Appends an Op{} instruction.", opcode);
let name = get_function_name(&inst.opname);
let init = get_init_list(&inst.operands);
// The debug section is split into three subsections
let section = match inst.opname.as_str() {
"OpSourceExtension" | "OpSource" | "OpSourceContinued" => {
quote! { debug_string_source }
}
"OpName" | "OpMemberName" => quote! { debug_names },
"OpModuleProcessed" => quote! { debug_module_processed },
other => panic!("Debug section instruction {} not handled", other),
};
quote! {
#[doc = #comment]
pub fn #name(&mut self,#(#params),*) {
#[allow(unused_mut)]
let mut inst = dr::Instruction::new(
spirv::Op::#opcode, None, None, vec![#(#init),*]);
#(#extras)*
self.module.debugs.push(inst);
self.module.#section.push(inst);
}
}
});
Expand Down
33 changes: 6 additions & 27 deletions rspirv/dr/build/autogen_debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ impl Builder {
None,
vec![dr::Operand::LiteralString(continued_source.into())],
);
self.module.debugs.push(inst);
self.module.debug_string_source.push(inst);
}
#[doc = "Appends an OpSource instruction."]
pub fn source(
Expand Down Expand Up @@ -40,7 +40,7 @@ impl Builder {
#[allow(clippy::identity_conversion)]
inst.operands.push(dr::Operand::LiteralString(v.into()));
}
self.module.debugs.push(inst);
self.module.debug_string_source.push(inst);
}
#[doc = "Appends an OpSourceExtension instruction."]
pub fn source_extension(&mut self, extension: impl Into<String>) {
Expand All @@ -51,7 +51,7 @@ impl Builder {
None,
vec![dr::Operand::LiteralString(extension.into())],
);
self.module.debugs.push(inst);
self.module.debug_string_source.push(inst);
}
#[doc = "Appends an OpName instruction."]
pub fn name(&mut self, target: spirv::Word, name: impl Into<String>) {
Expand All @@ -65,7 +65,7 @@ impl Builder {
dr::Operand::LiteralString(name.into()),
],
);
self.module.debugs.push(inst);
self.module.debug_names.push(inst);
}
#[doc = "Appends an OpMemberName instruction."]
pub fn member_name(&mut self, ty: spirv::Word, member: u32, name: impl Into<String>) {
Expand All @@ -80,28 +80,7 @@ impl Builder {
dr::Operand::LiteralString(name.into()),
],
);
self.module.debugs.push(inst);
}
#[doc = "Appends an OpLine instruction."]
pub fn line(&mut self, file: spirv::Word, line: u32, column: u32) {
#[allow(unused_mut)]
let mut inst = dr::Instruction::new(
spirv::Op::Line,
None,
None,
vec![
dr::Operand::IdRef(file),
dr::Operand::LiteralInt32(line),
dr::Operand::LiteralInt32(column),
],
);
self.module.debugs.push(inst);
}
#[doc = "Appends an OpNoLine instruction."]
pub fn no_line(&mut self) {
#[allow(unused_mut)]
let mut inst = dr::Instruction::new(spirv::Op::NoLine, None, None, vec![]);
self.module.debugs.push(inst);
self.module.debug_names.push(inst);
}
#[doc = "Appends an OpModuleProcessed instruction."]
pub fn module_processed(&mut self, process: impl Into<String>) {
Expand All @@ -112,6 +91,6 @@ impl Builder {
None,
vec![dr::Operand::LiteralString(process.into())],
);
self.module.debugs.push(inst);
self.module.debug_module_processed.push(inst);
}
}
49 changes: 46 additions & 3 deletions rspirv/dr/build/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ impl Builder {

/// Select a function to insert instructions into by name
pub fn select_function_by_name(&mut self, name: &str) -> BuildResult<()> {
for dbg in &self.module.debugs {
for dbg in &self.module.debug_names {
if dbg.class.opcode == spirv::Op::Name {
if let dr::Operand::IdRef(target_id) = dbg.operands[0] {
if let dr::Operand::LiteralString(found_name) = &dbg.operands[1] {
Expand Down Expand Up @@ -602,6 +602,47 @@ impl Builder {
self.insert_into_block(InsertPoint::End, inst)?;
Ok(_id)
}

/// Appends an `OpLine` instruction.
///
/// If a block is currently selected, the `OpLine` is inserted into that block. If no block is
/// currently selected, the `OpLine` is inserted into `types_global_values`.
pub fn line(&mut self, file: spirv::Word, line: u32, column: u32) {
let inst = dr::Instruction::new(
spirv::Op::Line,
None,
None,
vec![
dr::Operand::IdRef(file),
dr::Operand::LiteralInt32(line),
dr::Operand::LiteralInt32(column),
],
);
if self.selected_block.is_some() {
self.insert_into_block(InsertPoint::End, inst)
.expect("Internal error: insert_into_block failed when selected_block was Some");
} else {
// types_global_values is the only valid section (other than functions) that
// OpLine/OpNoLine can be placed in, so put it there.
self.module.types_global_values.push(inst);
}
}

/// Appends an `OpNoLine` instruction.
///
/// If a block is currently selected, the `OpNoLine` is inserted into that block. If no block
/// is currently selected, the `OpNoLine` is inserted into `types_global_values`.
pub fn no_line(&mut self) {
let inst = dr::Instruction::new(spirv::Op::NoLine, None, None, vec![]);
if self.selected_block.is_some() {
self.insert_into_block(InsertPoint::End, inst)
.expect("Internal error: insert_into_block failed when selected_block was Some");
} else {
// types_global_values is the only valid section (other than functions) that
// OpLine/OpNoLine can be placed in, so put it there.
self.module.types_global_values.push(inst);
}
}
}

include!("autogen_type.rs");
Expand All @@ -625,7 +666,7 @@ impl Builder {

pub fn string(&mut self, s: impl Into<String>) -> spirv::Word {
let id = self.id();
self.module.debugs.push(dr::Instruction::new(
self.module.debug_string_source.push(dr::Instruction::new(
spirv::Op::String,
None,
Some(id),
Expand Down Expand Up @@ -913,7 +954,9 @@ mod tests {
+ module.entry_points.len()
+ module.types_global_values.len()
+ module.execution_modes.len()
+ module.debugs.len()
+ module.debug_string_source.len()
+ module.debug_names.len()
+ module.debug_module_processed.len()
+ module.annotations.len())
+ (if module.memory_model.is_some() { 1 } else { 0 })
== 1
Expand Down
28 changes: 21 additions & 7 deletions rspirv/dr/constructs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,12 @@ pub struct Module {
pub entry_points: Vec<Instruction>,
/// All execution mode declarations, using OpExecutionMode.
pub execution_modes: Vec<Instruction>,
/// All non-location debug instructions.
pub debugs: Vec<Instruction>,
/// Debug subsection: All OpString, OpSourceExtension, OpSource, and OpSourceContinued.
pub debug_string_source: Vec<Instruction>,
/// Debug subsection: All OpName and all OpMemberName.
pub debug_names: Vec<Instruction>,
/// Debug subsection: All OpModuleProcessed instructions.
pub debug_module_processed: Vec<Instruction>,
Comment on lines +37 to +42
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tiny nit pick: looks like all the other names are pluralized, so I'd expect debug_string_sources and debug_module_processeds.

/// All annotation instructions.
pub annotations: Vec<Instruction>,
/// All types, constants, and global variables.
Expand Down Expand Up @@ -112,7 +116,9 @@ impl Module {
memory_model: None,
entry_points: vec![],
execution_modes: vec![],
debugs: vec![],
debug_string_source: vec![],
debug_names: vec![],
debug_module_processed: vec![],
annotations: vec![],
types_global_values: vec![],
functions: vec![],
Expand All @@ -128,7 +134,9 @@ impl Module {
.chain(&self.memory_model)
.chain(&self.entry_points)
.chain(&self.execution_modes)
.chain(&self.debugs)
.chain(&self.debug_string_source)
.chain(&self.debug_names)
.chain(&self.debug_module_processed)
.chain(&self.annotations)
.chain(&self.types_global_values)
}
Expand All @@ -142,7 +150,9 @@ impl Module {
.chain(&mut self.memory_model)
.chain(&mut self.entry_points)
.chain(&mut self.execution_modes)
.chain(&mut self.debugs)
.chain(&mut self.debug_string_source)
.chain(&mut self.debug_names)
.chain(&mut self.debug_module_processed)
.chain(&mut self.annotations)
.chain(&mut self.types_global_values)
}
Expand All @@ -156,7 +166,9 @@ impl Module {
.chain(&self.memory_model)
.chain(&self.entry_points)
.chain(&self.execution_modes)
.chain(&self.debugs)
.chain(&self.debug_string_source)
.chain(&self.debug_names)
.chain(&self.debug_module_processed)
.chain(&self.annotations)
.chain(&self.types_global_values)
.chain(self.functions.iter().flat_map(|f| f.all_inst_iter()))
Expand All @@ -171,7 +183,9 @@ impl Module {
.chain(&mut self.memory_model)
.chain(&mut self.entry_points)
.chain(&mut self.execution_modes)
.chain(&mut self.debugs)
.chain(&mut self.debug_string_source)
.chain(&mut self.debug_names)
.chain(&mut self.debug_module_processed)
.chain(&mut self.annotations)
.chain(&mut self.types_global_values)
.chain(
Expand Down
18 changes: 13 additions & 5 deletions rspirv/dr/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,19 @@ impl binary::Consumer for Loader {
spirv::Op::MemoryModel => self.module.memory_model = Some(inst),
spirv::Op::EntryPoint => self.module.entry_points.push(inst),
spirv::Op::ExecutionMode => self.module.execution_modes.push(inst),
opcode if grammar::reflect::is_nonlocation_debug(opcode) => {
self.module.debugs.push(inst)
spirv::Op::String
| spirv::Op::SourceExtension
| spirv::Op::Source
| spirv::Op::SourceContinued => self.module.debug_string_source.push(inst),
spirv::Op::Name | spirv::Op::MemberName => self.module.debug_names.push(inst),
spirv::Op::ModuleProcessed => self.module.debug_module_processed.push(inst),
opcode if grammar::reflect::is_location_debug(opcode) => {
match &mut self.block {
Some(block) => block.instructions.push(inst),
// types_global_values is the only valid section (other than functions) that
// OpLine/OpNoLine can be placed in, so put it there.
None => self.module.types_global_values.push(inst),
}
}
opcode if grammar::reflect::is_annotation(opcode) => self.module.annotations.push(inst),
opcode
Expand Down Expand Up @@ -185,9 +196,6 @@ impl binary::Consumer for Loader {
.blocks
.push(self.block.take().unwrap())
}
spirv::Op::ModuleProcessed | spirv::Op::Line => {
// Ignore
}
_ => {
if self.block.is_none() {
return ParseAction::Error(Box::new(Error::DetachedInstruction(Some(inst))));
Expand Down