Skip to content

Commit

Permalink
Handle duplicate names to be able to handle OpCopyMemory{,Sized} (#155)
Browse files Browse the repository at this point in the history
* Run clean cargo build to update some forgotten stuff

* Handle duplicate names to be able to handle OpCopyMemory{,Sized}
  • Loading branch information
khyperia authored Aug 24, 2020
1 parent 16265b8 commit 2efd1cd
Show file tree
Hide file tree
Showing 7 changed files with 247 additions and 47 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 9 additions & 8 deletions autogen/dr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@ fn get_param_list(
let mut type_generics = TokenStream::new();
let mut list: Vec<_> = params
.iter()
.filter_map(|param| {
let name = get_param_name(param);
.enumerate()
.filter_map(|(param_index, param)| {
let name = get_param_name(params, param_index);
let kind = get_enum_underlying_type(&param.kind, true);
if param.kind == "IdResult" {
if keep_result_id {
Expand Down Expand Up @@ -94,13 +95,14 @@ fn get_function_name_with_prepend(prepend: &str, opname: &str) -> TokenStream {
fn get_init_list(params: &[structs::Operand]) -> Vec<TokenStream> {
params
.iter()
.filter_map(|param| {
.enumerate()
.filter_map(|(param_index, param)| {
if param.quantifier == structs::Quantifier::One {
if param.kind == "IdResult" || param.kind == "IdResultType" {
// These two operands are not stored in the operands field.
None
} else {
let name = get_param_name(param);
let name = get_param_name(params, param_index);
let kind = get_dr_operand_kind(&param.kind);
Some(if kind == "LiteralString" {
quote! { dr::Operand::LiteralString(#name.into()) }
Expand All @@ -122,8 +124,9 @@ fn get_push_extras(
) -> Vec<TokenStream> {
let mut list: Vec<_> = params
.iter()
.filter_map(|param| {
let name = get_param_name(param);
.enumerate()
.filter_map(|(param_index, param)| {
let name = get_param_name(params, param_index);
match param.quantifier {
structs::Quantifier::One => None,
structs::Quantifier::ZeroOrOne => {
Expand Down Expand Up @@ -417,8 +420,6 @@ pub fn gen_dr_builder_normal_insts(grammar: &structs::Grammar) -> TokenStream {
inst.opname == "OpTypeOpaque" ||
inst.opname == "OpUndef" ||
inst.opname == "OpVariable" ||
inst.opname == "OpCopyMemory" ||
inst.opname == "OpCopyMemorySized" ||
inst.opname.starts_with("OpType");
!skip
}).map(|inst| {
Expand Down
25 changes: 12 additions & 13 deletions autogen/sr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,13 @@ struct OperandTokens {
}

impl OperandTokens {
fn new(operand: &structs::Operand, inst: Option<&structs::Instruction>) -> Self {
let name = get_param_name(operand);
fn new(
operands: &[structs::Operand],
operand_index: usize,
inst: Option<&structs::Instruction>,
) -> Self {
let operand = &operands[operand_index];
let name = get_param_name(operands, operand_index);
let iter = Ident::new(OPERAND_ITER, Span::call_site());

let (ty, lift_value, first_name, second_name) = match operand.kind.as_str() {
Expand Down Expand Up @@ -217,10 +222,8 @@ pub fn gen_sr_code_from_operand_kind_grammar(
.iter()
.map(|enumerant| {
// Parameters for this enumerant
let types: Vec<_> = enumerant
.parameters
.iter()
.map(|p| OperandTokens::new(p, None).quantified_type)
let types: Vec<_> = (0..enumerant.parameters.len())
.map(|p| OperandTokens::new(&enumerant.parameters, p, None).quantified_type)
.collect();
let params = if types.is_empty() {
quote! {}
Expand Down Expand Up @@ -287,18 +290,14 @@ pub fn gen_sr_code_from_instruction_grammar(
// Get the token for its enumerant
let inst_name = &inst.opname[2..];

// todo: these have parameters with duplicate names in the .json - just skip them for now
if inst_name == "CopyMemory" || inst_name == "CopyMemorySized" {
continue;
}
let name_ident = Ident::new(inst_name, Span::call_site());
let type_name = if inst.opname.len() > TYPE_PREFIX_LENGTH {
&inst.opname[TYPE_PREFIX_LENGTH..]
} else {
"_"
};

let type_name = if type_name.chars().nth(0).unwrap().is_ascii_digit() {
let type_name = if type_name.chars().next().unwrap().is_ascii_digit() {
format!("p_{}", type_name)
} else {
type_name.to_string()
Expand All @@ -313,11 +312,11 @@ pub fn gen_sr_code_from_instruction_grammar(
field_lifts.clear();

// Compose the token stream for all parameters
for operand in inst.operands.iter() {
for (index, operand) in inst.operands.iter().enumerate() {
if operand.kind.starts_with("IdResult") {
continue;
}
let tokens = OperandTokens::new(operand, Some(&inst));
let tokens = OperandTokens::new(&inst.operands, index, Some(&inst));
field_names.push(tokens.name);
field_types.push(tokens.quantified_type);
field_lifts.push(tokens.lift_expression);
Expand Down
35 changes: 27 additions & 8 deletions autogen/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,20 +66,39 @@ pub fn get_enum_underlying_type(kind: &str, generic_string: bool) -> TokenStream
}

/// Returns a suitable name for the given parameter.
pub fn get_param_name(param: &structs::Operand) -> Ident {
let mut name = if param.name.len() == 0 {
if param.kind == "IdResultType" {
"result_type".to_string()
pub fn get_param_name(params: &[structs::Operand], param_index: usize) -> Ident {
fn get_original_name(param: &structs::Operand) -> &str {
if param.name.is_empty() {
if param.kind == "IdResultType" {
"result_type"
} else {
&param.kind
}
} else {
param.kind.to_snake_case()
&param.name
}
} else {
param.name.to_snake_case()
};
}

let param = &params[param_index];

let raw_name = get_original_name(param);

// OpCopyMemory and OpCopyMemorySized have duplicate field names
let duplicate_count = params
.iter()
.take(param_index)
.filter(|p| get_original_name(p) == raw_name)
.count();

let mut name = raw_name.to_snake_case();

if name == "type" {
name = "ty".to_owned();
}

if duplicate_count > 0 {
name = format!("{}_{}", name, duplicate_count + 1);
}

as_ident(&name)
}
146 changes: 130 additions & 16 deletions rspirv/dr/build/autogen_norm_insts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ impl Builder {
Ok(())
}
#[doc = "Appends an OpFunctionCall instruction to the current block."]
pub fn function_call<T: AsRef<[spirv::Word]>>(
pub fn function_call<T: IntoIterator<Item = spirv::Word>>(
&mut self,
result_type: spirv::Word,
result_id: Option<spirv::Word>,
Expand All @@ -34,18 +34,13 @@ impl Builder {
Some(_id),
vec![dr::Operand::IdRef(function)],
);
inst.operands.extend(
argument_0_argument_1
.as_ref()
.iter()
.cloned()
.map(dr::Operand::IdRef),
);
inst.operands
.extend(argument_0_argument_1.into_iter().map(dr::Operand::IdRef));
self.insert_into_block(InsertPoint::End, inst)?;
Ok(_id)
}
#[doc = "Appends an OpFunctionCall instruction to the current block."]
pub fn insert_function_call<T: AsRef<[spirv::Word]>>(
pub fn insert_function_call<T: IntoIterator<Item = spirv::Word>>(
&mut self,
insert_point: InsertPoint,
result_type: spirv::Word,
Expand All @@ -61,13 +56,8 @@ impl Builder {
Some(_id),
vec![dr::Operand::IdRef(function)],
);
inst.operands.extend(
argument_0_argument_1
.as_ref()
.iter()
.cloned()
.map(dr::Operand::IdRef),
);
inst.operands
.extend(argument_0_argument_1.into_iter().map(dr::Operand::IdRef));
self.insert_into_block(insert_point, inst)?;
Ok(_id)
}
Expand Down Expand Up @@ -218,6 +208,130 @@ impl Builder {
self.insert_into_block(insert_point, inst)?;
Ok(())
}
#[doc = "Appends an OpCopyMemory instruction to the current block."]
pub fn copy_memory<T: IntoIterator<Item = dr::Operand>>(
&mut self,
target: spirv::Word,
source: spirv::Word,
memory_access: Option<spirv::MemoryAccess>,
memory_access_2: Option<spirv::MemoryAccess>,
additional_params: T,
) -> BuildResult<()> {
#[allow(unused_mut)]
let mut inst = dr::Instruction::new(
spirv::Op::CopyMemory,
None,
None,
vec![dr::Operand::IdRef(target), dr::Operand::IdRef(source)],
);
if let Some(v) = memory_access {
#[allow(clippy::identity_conversion)]
inst.operands.push(dr::Operand::MemoryAccess(v.into()));
}
if let Some(v) = memory_access_2 {
#[allow(clippy::identity_conversion)]
inst.operands.push(dr::Operand::MemoryAccess(v.into()));
}
inst.operands.extend(additional_params);
self.insert_into_block(InsertPoint::End, inst)?;
Ok(())
}
#[doc = "Appends an OpCopyMemory instruction to the current block."]
pub fn insert_copy_memory<T: IntoIterator<Item = dr::Operand>>(
&mut self,
insert_point: InsertPoint,
target: spirv::Word,
source: spirv::Word,
memory_access: Option<spirv::MemoryAccess>,
memory_access_2: Option<spirv::MemoryAccess>,
additional_params: T,
) -> BuildResult<()> {
#[allow(unused_mut)]
let mut inst = dr::Instruction::new(
spirv::Op::CopyMemory,
None,
None,
vec![dr::Operand::IdRef(target), dr::Operand::IdRef(source)],
);
if let Some(v) = memory_access {
#[allow(clippy::identity_conversion)]
inst.operands.push(dr::Operand::MemoryAccess(v.into()));
}
if let Some(v) = memory_access_2 {
#[allow(clippy::identity_conversion)]
inst.operands.push(dr::Operand::MemoryAccess(v.into()));
}
inst.operands.extend(additional_params);
self.insert_into_block(insert_point, inst)?;
Ok(())
}
#[doc = "Appends an OpCopyMemorySized instruction to the current block."]
pub fn copy_memory_sized<T: IntoIterator<Item = dr::Operand>>(
&mut self,
target: spirv::Word,
source: spirv::Word,
size: spirv::Word,
memory_access: Option<spirv::MemoryAccess>,
memory_access_2: Option<spirv::MemoryAccess>,
additional_params: T,
) -> BuildResult<()> {
#[allow(unused_mut)]
let mut inst = dr::Instruction::new(
spirv::Op::CopyMemorySized,
None,
None,
vec![
dr::Operand::IdRef(target),
dr::Operand::IdRef(source),
dr::Operand::IdRef(size),
],
);
if let Some(v) = memory_access {
#[allow(clippy::identity_conversion)]
inst.operands.push(dr::Operand::MemoryAccess(v.into()));
}
if let Some(v) = memory_access_2 {
#[allow(clippy::identity_conversion)]
inst.operands.push(dr::Operand::MemoryAccess(v.into()));
}
inst.operands.extend(additional_params);
self.insert_into_block(InsertPoint::End, inst)?;
Ok(())
}
#[doc = "Appends an OpCopyMemorySized instruction to the current block."]
pub fn insert_copy_memory_sized<T: IntoIterator<Item = dr::Operand>>(
&mut self,
insert_point: InsertPoint,
target: spirv::Word,
source: spirv::Word,
size: spirv::Word,
memory_access: Option<spirv::MemoryAccess>,
memory_access_2: Option<spirv::MemoryAccess>,
additional_params: T,
) -> BuildResult<()> {
#[allow(unused_mut)]
let mut inst = dr::Instruction::new(
spirv::Op::CopyMemorySized,
None,
None,
vec![
dr::Operand::IdRef(target),
dr::Operand::IdRef(source),
dr::Operand::IdRef(size),
],
);
if let Some(v) = memory_access {
#[allow(clippy::identity_conversion)]
inst.operands.push(dr::Operand::MemoryAccess(v.into()));
}
if let Some(v) = memory_access_2 {
#[allow(clippy::identity_conversion)]
inst.operands.push(dr::Operand::MemoryAccess(v.into()));
}
inst.operands.extend(additional_params);
self.insert_into_block(insert_point, inst)?;
Ok(())
}
#[doc = "Appends an OpAccessChain instruction to the current block."]
pub fn access_chain<T: IntoIterator<Item = spirv::Word>>(
&mut self,
Expand Down
Loading

0 comments on commit 2efd1cd

Please sign in to comment.