[ir] support function argument names (#270)

This commit is contained in:
Dzmitry Malyshau 2020-11-11 15:34:37 -05:00 committed by GitHub
parent a54800afc1
commit 8b56f3ef96
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 112 additions and 104 deletions

View File

@ -422,10 +422,10 @@ pub fn write<'a>(
.as_deref()
.unwrap_or("void"),
name,
func.parameter_types
func.arguments
.iter()
.map(|ty| write_type(
*ty,
.map(|arg| write_type(
arg.ty,
&module.types,
&module.constants,
&structs,
@ -658,15 +658,22 @@ pub fn write<'a>(
global_vars: &module.global_variables,
local_vars: &func.local_variables,
functions: &module.functions,
parameter_types: &func.parameter_types,
arguments: &func.arguments,
},
)?;
let args: FastHashMap<_, _> = func
.parameter_types
.arguments
.iter()
.enumerate()
.map(|(pos, _)| (pos as u32, format!("arg_{}", pos)))
.map(|(pos, arg)| {
let name = arg
.name
.clone()
.filter(|ident| is_valid_ident(ident))
.unwrap_or_else(|| format!("arg_{}", pos + 1));
(pos as u32, name)
})
.collect();
writeln!(
@ -685,20 +692,19 @@ pub fn write<'a>(
.as_deref()
.unwrap_or("void"),
name,
func.parameter_types
func.arguments
.iter()
.zip(args.values())
.map::<Result<_, Error>, _>(|(ty, name)| {
.enumerate()
.map::<Result<_, Error>, _>(|(pos, arg)| {
let ty = write_type(
*ty,
arg.ty,
&module.types,
&module.constants,
&structs,
None,
&mut manager,
)?;
Ok(format!("{} {}", ty, name))
Ok(format!("{} {}", ty, args[&(pos as u32)]))
})
.collect::<Result<Vec<_>, _>>()?
.join(","),
@ -1035,7 +1041,7 @@ fn write_expression<'a, 'b>(
.join(","),
))
}
Expression::FunctionParameter(pos) => Cow::Borrowed(builder.args.get(&pos).unwrap()),
Expression::FunctionArgument(pos) => Cow::Borrowed(builder.args.get(&pos).unwrap()),
Expression::GlobalVariable(handle) => Cow::Borrowed(builder.globals.get(&handle).unwrap()),
Expression::LocalVariable(handle) => {
Cow::Borrowed(builder.locals_lookup.get(&handle).unwrap())

View File

@ -383,12 +383,12 @@ impl<W: Write> Writer<W> {
_ => return Err(Error::UnsupportedCompose(ty)),
}
}
crate::Expression::FunctionParameter(index) => {
crate::Expression::FunctionArgument(index) => {
let fun_handle = match context.origin {
FunctionOrigin::Handle(handle) => handle,
FunctionOrigin::EntryPoint(_) => unreachable!(),
};
let name = &self.names[&NameKey::FunctionParameter(fun_handle, index)];
let name = &self.names[&NameKey::FunctionArgument(fun_handle, index)];
write!(self.out, "{}", name)?;
}
crate::Expression::GlobalVariable(handle) => {
@ -900,7 +900,7 @@ impl<W: Write> Writer<W> {
global_vars: &module.global_variables,
local_vars: &fun.local_variables,
functions: &module.functions,
parameter_types: &fun.parameter_types,
arguments: &fun.arguments,
},
)?;
@ -911,10 +911,10 @@ impl<W: Write> Writer<W> {
};
writeln!(self.out, "{} {}(", result_type_name, fun_name)?;
for (index, &ty) in fun.parameter_types.iter().enumerate() {
let name = &self.names[&NameKey::FunctionParameter(fun_handle, index as u32)];
let param_type_name = &self.names[&NameKey::Type(ty)];
let separator = separate(index + 1 == fun.parameter_types.len());
for (index, arg) in fun.arguments.iter().enumerate() {
let name = &self.names[&NameKey::FunctionArgument(fun_handle, index as u32)];
let param_type_name = &self.names[&NameKey::Type(arg.ty)];
let separator = separate(index + 1 == fun.arguments.len());
writeln!(self.out, "\t{} {}{}", param_type_name, name, separator)?;
}
writeln!(self.out, ") {{")?;
@ -949,7 +949,7 @@ impl<W: Write> Writer<W> {
global_vars: &module.global_variables,
local_vars: &fun.local_variables,
functions: &module.functions,
parameter_types: &fun.parameter_types,
arguments: &fun.arguments,
},
)?;

View File

@ -324,21 +324,18 @@ impl Writer {
let return_type_id =
self.get_function_return_type(ir_function.return_type, &ir_module.types);
let mut parameter_type_ids = Vec::with_capacity(ir_function.parameter_types.len());
let mut parameter_type_ids = Vec::with_capacity(ir_function.arguments.len());
let mut function_parameter_pointer_ids = vec![];
for parameter_type in ir_function.parameter_types.iter() {
for argument in ir_function.arguments.iter() {
let id = self.generate_id();
let pointer_id = self.get_pointer_id(
&ir_module.types,
*parameter_type,
crate::StorageClass::Function,
);
let pointer_id =
self.get_pointer_id(&ir_module.types, argument.ty, crate::StorageClass::Function);
function_parameter_pointer_ids.push(pointer_id);
parameter_type_ids
.push(self.get_type_id(&ir_module.types, LookupType::Handle(*parameter_type)));
.push(self.get_type_id(&ir_module.types, LookupType::Handle(argument.ty)));
function
.parameters
.push(super::instructions::instruction_function_parameter(
@ -868,21 +865,21 @@ impl Writer {
block: &mut Block,
function: &mut Function,
) -> Result<WriteExpressionOutput, Error> {
match expression {
match *expression {
crate::Expression::Access { base, index } => {
let id = self.generate_id();
let (base_id, base_lookup_ty) = self.write_expression(
ir_module,
ir_function,
&ir_function.expressions[*base],
&ir_function.expressions[base],
block,
function,
)?;
let (index_id, _) = self.write_expression(
ir_module,
ir_function,
&ir_function.expressions[*index],
&ir_function.expressions[index],
block,
function,
)?;
@ -926,7 +923,7 @@ impl Writer {
.write_expression(
ir_module,
ir_function,
&ir_function.expressions[*base],
&ir_function.expressions[base],
block,
function,
)
@ -947,7 +944,7 @@ impl Writer {
)
}
crate::TypeInner::Struct { ref members } => {
let member = &members[*index as usize];
let member = &members[index as usize];
let type_id =
self.get_type_id(&ir_module.types, LookupType::Handle(member.ty));
(
@ -966,7 +963,7 @@ impl Writer {
width: 4,
}),
);
let const_id = self.create_constant(const_ty_id, &[*index]);
let const_id = self.create_constant(const_ty_id, &[index]);
block
.body
@ -985,18 +982,18 @@ impl Writer {
Ok((load_id, Some(lookup_ty)))
}
crate::Expression::GlobalVariable(handle) => {
let var = &ir_module.global_variables[*handle];
let id = self.get_global_variable_id(&ir_module, *handle);
let var = &ir_module.global_variables[handle];
let id = self.get_global_variable_id(&ir_module, handle);
Ok((id, Some(LookupType::Handle(var.ty))))
}
crate::Expression::Constant(handle) => {
let var = &ir_module.constants[*handle];
let id = self.get_constant_id(*handle, ir_module);
let var = &ir_module.constants[handle];
let id = self.get_constant_id(handle, ir_module);
Ok((id, Some(LookupType::Handle(var.ty))))
}
crate::Expression::Compose { ty, ref components } => {
let base_type_id = self.get_type_id(&ir_module.types, LookupType::Handle(*ty));
let base_type_id = self.get_type_id(&ir_module.types, LookupType::Handle(ty));
let mut constituent_ids = Vec::with_capacity(components.len());
for component in components {
@ -1013,7 +1010,7 @@ impl Writer {
}
let constituent_ids_slice = constituent_ids.as_slice();
let id = match ir_module.types[*ty].inner {
let id = match ir_module.types[ty].inner {
crate::TypeInner::Vector { .. } => {
self.write_composite_construct(base_type_id, constituent_ids_slice, block)
}
@ -1053,14 +1050,14 @@ impl Writer {
_ => unreachable!(),
};
Ok((id, Some(LookupType::Handle(*ty))))
Ok((id, Some(LookupType::Handle(ty))))
}
crate::Expression::Binary { op, left, right } => {
match op {
crate::BinaryOperator::Multiply => {
let id = self.generate_id();
let left_expression = &ir_function.expressions[*left];
let right_expression = &ir_function.expressions[*right];
let left_expression = &ir_function.expressions[left];
let right_expression = &ir_function.expressions[right];
let (left_id, left_lookup_ty) = self.write_expression(
ir_module,
ir_function,
@ -1205,7 +1202,7 @@ impl Writer {
}
}
crate::Expression::LocalVariable(variable) => {
let var = &ir_function.local_variables[*variable];
let var = &ir_function.local_variables[variable];
function
.variables
.iter()
@ -1213,25 +1210,25 @@ impl Writer {
.map(|local_var| (local_var.id, Some(LookupType::Handle(var.ty))))
.ok_or_else(|| Error::UnknownLocalVariable(var.clone()))
}
crate::Expression::FunctionParameter(index) => {
let handle = ir_function.parameter_types.get(*index as usize).unwrap();
let type_id = self.get_type_id(&ir_module.types, LookupType::Handle(*handle));
crate::Expression::FunctionArgument(index) => {
let handle = ir_function.arguments[index as usize].ty;
let type_id = self.get_type_id(&ir_module.types, LookupType::Handle(handle));
let load_id = self.generate_id();
block.body.push(super::instructions::instruction_load(
type_id,
load_id,
function.parameters[*index as usize].result_id.unwrap(),
function.parameters[index as usize].result_id.unwrap(),
None,
));
Ok((load_id, Some(LookupType::Handle(*handle))))
Ok((load_id, Some(LookupType::Handle(handle))))
}
crate::Expression::Call {
ref origin,
ref arguments,
} => match origin {
} => match *origin {
crate::FunctionOrigin::Local(local_function) => {
let origin_function = &ir_module.functions[*local_function];
let origin_function = &ir_module.functions[local_function];
let id = self.generate_id();
let mut argument_ids = vec![];
@ -1306,7 +1303,7 @@ impl Writer {
let (expr_id, expr_type) = self.write_expression(
ir_module,
ir_function,
&ir_function.expressions[*expr],
&ir_function.expressions[expr],
block,
function,
)?;
@ -1321,10 +1318,10 @@ impl Writer {
} => {
let kind_type_id = self.get_type_id(
&ir_module.types,
LookupType::Local(LocalType::Scalar { kind: *kind, width }),
LookupType::Local(LocalType::Scalar { kind, width }),
);
if *convert {
if convert {
super::instructions::instruction_bit_cast(kind_type_id, id, expr_id)
} else {
match (expr_kind, kind) {
@ -1375,7 +1372,7 @@ impl Writer {
depth_ref: _,
} => {
// image
let image_expression = &ir_function.expressions[*image];
let image_expression = &ir_function.expressions[image];
let (image_id, image_lookup_ty) = self.write_expression(
ir_module,
ir_function,
@ -1414,7 +1411,7 @@ impl Writer {
);
// sampler
let sampler_expression = &ir_function.expressions[*sampler];
let sampler_expression = &ir_function.expressions[sampler];
let (sampler_id, sampler_lookup_ty) = self.write_expression(
ir_module,
ir_function,
@ -1440,7 +1437,7 @@ impl Writer {
};
// coordinate
let coordinate_expression = &ir_function.expressions[*coordinate];
let coordinate_expression = &ir_function.expressions[coordinate];
let (coordinate_id, coordinate_lookup_ty) = self.write_expression(
ir_module,
ir_function,

View File

@ -57,13 +57,13 @@ impl Program {
handle: Handle<crate::Expression>,
) -> Result<&crate::TypeInner, ErrorKind> {
let functions = Arena::new(); //TODO
let parameter_types: Vec<Handle<Type>> = vec![]; //TODO
let arguments = Vec::new(); //TODO
let resolve_ctx = ResolveContext {
constants: &self.module.constants,
global_vars: &self.module.global_variables,
local_vars: &self.context.local_variables,
functions: &functions,
parameter_types: &parameter_types,
arguments: &arguments,
};
match self.context.typifier.grow(
handle,

View File

@ -1007,7 +1007,7 @@ pomelo! {
function_header ::= fully_specified_type(t) Identifier(n) LeftParen {
Function {
name: Some(n.1),
parameter_types: vec![],
arguments: vec![],
return_type: t.1,
global_usage: vec![],
local_variables: Arena::<LocalVariable>::new(),

View File

@ -46,7 +46,7 @@ pub enum Error {
InvalidAsType(Handle<crate::Type>),
InconsistentComparisonSampling(Handle<crate::Type>),
WrongFunctionResultType(spirv::Word),
WrongFunctionParameterType(spirv::Word),
WrongFunctionArgumentType(spirv::Word),
MissingDecoration(spirv::Decoration),
BadString,
IncompleteData,

View File

@ -69,7 +69,7 @@ impl<I: Iterator<Item = u32>> super::Parser<I> {
}
crate::Function {
name: self.future_decor.remove(&fun_id).and_then(|dec| dec.name),
parameter_types: Vec::with_capacity(ft.parameter_type_ids.len()),
arguments: Vec::with_capacity(ft.parameter_type_ids.len()),
return_type: if self.lookup_void_type.contains(&result_type) {
None
} else {
@ -83,7 +83,7 @@ impl<I: Iterator<Item = u32>> super::Parser<I> {
};
// read parameters
for i in 0..fun.parameter_types.capacity() {
for i in 0..fun.arguments.capacity() {
match self.next_inst()? {
Instruction {
op: spirv::Op::FunctionParameter,
@ -93,7 +93,7 @@ impl<I: Iterator<Item = u32>> super::Parser<I> {
let id = self.next()?;
let handle = fun
.expressions
.append(crate::Expression::FunctionParameter(i as u32));
.append(crate::Expression::FunctionArgument(i as u32));
self.lookup_expression
.insert(id, LookupExpression { type_id, handle });
//Note: we redo the lookup in order to work around `self` borrowing
@ -104,10 +104,11 @@ impl<I: Iterator<Item = u32>> super::Parser<I> {
.lookup(fun_type)?
.parameter_type_ids[i]
{
return Err(Error::WrongFunctionParameterType(type_id));
return Err(Error::WrongFunctionArgumentType(type_id));
}
let ty = self.lookup_type.lookup(type_id)?.handle;
fun.parameter_types.push(ty);
fun.arguments
.push(crate::FunctionArgument { name: None, ty });
}
Instruction { op, .. } => return Err(Error::InvalidParameter(op)),
}

View File

@ -97,7 +97,7 @@ struct StatementContext<'input, 'temp, 'out> {
types: &'out mut Arena<crate::Type>,
constants: &'out mut Arena<crate::Constant>,
global_vars: &'out Arena<crate::GlobalVariable>,
parameter_types: &'out [Handle<crate::Type>],
arguments: &'out [crate::FunctionArgument],
}
impl<'a> StatementContext<'a, '_, '_> {
@ -110,7 +110,7 @@ impl<'a> StatementContext<'a, '_, '_> {
types: self.types,
constants: self.constants,
global_vars: self.global_vars,
parameter_types: self.parameter_types,
arguments: self.arguments,
}
}
@ -123,7 +123,7 @@ impl<'a> StatementContext<'a, '_, '_> {
constants: self.constants,
global_vars: self.global_vars,
local_vars: self.variables,
parameter_types: self.parameter_types,
arguments: self.arguments,
}
}
}
@ -136,7 +136,7 @@ struct ExpressionContext<'input, 'temp, 'out> {
constants: &'out mut Arena<crate::Constant>,
global_vars: &'out Arena<crate::GlobalVariable>,
local_vars: &'out Arena<crate::LocalVariable>,
parameter_types: &'out [Handle<crate::Type>],
arguments: &'out [crate::FunctionArgument],
}
impl<'a> ExpressionContext<'a, '_, '_> {
@ -149,7 +149,7 @@ impl<'a> ExpressionContext<'a, '_, '_> {
constants: self.constants,
global_vars: self.global_vars,
local_vars: self.local_vars,
parameter_types: self.parameter_types,
arguments: self.arguments,
}
}
@ -163,7 +163,7 @@ impl<'a> ExpressionContext<'a, '_, '_> {
global_vars: self.global_vars,
local_vars: self.local_vars,
functions: &functions,
parameter_types: self.parameter_types,
arguments: self.arguments,
};
match self
.typifier
@ -1545,19 +1545,22 @@ impl Parser {
lookup_ident.insert(name, expr_handle);
}
// read parameter list
let mut parameter_types = Vec::new();
let mut arguments = Vec::new();
lexer.expect(Token::Paren('('))?;
while !lexer.skip(Token::Paren(')')) {
if !parameter_types.is_empty() {
if !arguments.is_empty() {
lexer.expect(Token::Separator(','))?;
}
let (param_name, param_type) =
self.parse_variable_ident_decl(lexer, &mut module.types, &mut module.constants)?;
let param_index = parameter_types.len() as u32;
let param_index = arguments.len() as u32;
let expression_token =
expressions.append(crate::Expression::FunctionParameter(param_index));
expressions.append(crate::Expression::FunctionArgument(param_index));
lookup_ident.insert(param_name, expression_token);
parameter_types.push(param_type);
arguments.push(crate::FunctionArgument {
name: Some(param_name.to_string()),
ty: param_type,
});
}
// read return type
lexer.expect(Token::Arrow)?;
@ -1569,7 +1572,7 @@ impl Parser {
let mut fun = crate::Function {
name: Some(fun_name.to_string()),
parameter_types,
arguments,
return_type,
global_usage: Vec::new(),
local_variables: Arena::new(),
@ -1589,7 +1592,7 @@ impl Parser {
types: &mut module.types,
constants: &mut module.constants,
global_vars: &module.global_variables,
parameter_types: &fun.parameter_types,
arguments: &fun.arguments,
},
)?;
// done

View File

@ -584,7 +584,7 @@ pub enum Expression {
components: Vec<Handle<Expression>>,
},
/// Reference a function parameter, by its index.
FunctionParameter(u32),
FunctionArgument(u32),
/// Reference a global variable.
GlobalVariable(Handle<GlobalVariable>),
/// Reference a local variable.
@ -702,6 +702,17 @@ pub enum Statement {
},
}
/// A function argument.
#[derive(Debug)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub struct FunctionArgument {
/// Name of the argument, if any.
pub name: Option<String>,
/// Type of the argument.
pub ty: Handle<Type>,
}
/// A function defined in the module.
#[derive(Debug)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
@ -709,9 +720,8 @@ pub enum Statement {
pub struct Function {
/// Name of the function, if any.
pub name: Option<String>,
//pub control: spirv::FunctionControl,
/// The types of the parameters of this function.
pub parameter_types: Vec<Handle<Type>>,
/// Information about function argument.
pub arguments: Vec<FunctionArgument>,
/// The return type of this function, if any.
pub return_type: Option<Handle<Type>>,
/// Vector of global variable usages.

View File

@ -37,7 +37,7 @@ where
self.traverse_expr(comp);
}
}
E::FunctionParameter(_) | E::GlobalVariable(_) | E::LocalVariable(_) => {}
E::FunctionArgument(_) | E::GlobalVariable(_) | E::LocalVariable(_) => {}
E::Load { pointer } => {
self.traverse_expr(pointer);
}
@ -259,7 +259,7 @@ mod tests {
let mut function = crate::Function {
name: None,
parameter_types: Vec::new(),
arguments: Vec::new(),
return_type: None,
local_variables: Arena::new(),
expressions,

View File

@ -9,7 +9,7 @@ pub enum NameKey {
Type(Handle<crate::Type>),
StructMember(Handle<crate::Type>, u32),
Function(Handle<crate::Function>),
FunctionParameter(Handle<crate::Function>, u32),
FunctionArgument(Handle<crate::Function>, u32),
FunctionLocal(Handle<crate::Function>, Handle<crate::LocalVariable>),
EntryPoint(EntryPointIndex),
EntryPointLocal(EntryPointIndex, Handle<crate::LocalVariable>),
@ -21,9 +21,6 @@ pub struct Namer {
unique: FastHashMap<String, u32>,
}
const MAX_PARAM_COUNT: u32 = 100;
const PARAM_NAME: &str = "param";
impl Namer {
fn sanitize(string: &str) -> String {
let mut base = string
@ -73,9 +70,6 @@ impl Namer {
.map(|string| (string.to_string(), 0))
.collect(),
};
// Force the starting suffix for the function parameter names
// to be higher than whatever we assign explicitly.
this.unique.insert(PARAM_NAME.to_string(), MAX_PARAM_COUNT);
for (handle, var) in module.global_variables.iter() {
let name = this.call_or(&var.name, "global");
@ -97,12 +91,9 @@ impl Namer {
for (fun_handle, fun) in module.functions.iter() {
let fun_name = this.call_or(&fun.name, "function");
output.insert(NameKey::Function(fun_handle), fun_name);
if fun.parameter_types.len() >= MAX_PARAM_COUNT as usize {
unreachable!()
}
for (index, _) in fun.parameter_types.iter().enumerate() {
let name = format!("{}{}", PARAM_NAME, index + 1);
output.insert(NameKey::FunctionParameter(fun_handle, index as u32), name);
for (index, arg) in fun.arguments.iter().enumerate() {
let name = this.call_or(&arg.name, "param");
output.insert(NameKey::FunctionArgument(fun_handle, index as u32), name);
}
for (handle, var) in fun.local_variables.iter() {
let name = this.call_or(&var.name, "local");

View File

@ -66,7 +66,7 @@ pub struct ResolveContext<'a> {
pub global_vars: &'a Arena<crate::GlobalVariable>,
pub local_vars: &'a Arena<crate::LocalVariable>,
pub functions: &'a Arena<crate::Function>,
pub parameter_types: &'a [Handle<crate::Type>],
pub arguments: &'a [crate::FunctionArgument],
}
impl Typifier {
@ -168,8 +168,8 @@ impl Typifier {
},
crate::Expression::Constant(h) => Resolution::Handle(ctx.constants[h].ty),
crate::Expression::Compose { ty, .. } => Resolution::Handle(ty),
crate::Expression::FunctionParameter(index) => {
Resolution::Handle(ctx.parameter_types[index as usize])
crate::Expression::FunctionArgument(index) => {
Resolution::Handle(ctx.arguments[index as usize].ty)
}
crate::Expression::GlobalVariable(h) => Resolution::Handle(ctx.global_vars[h].ty),
crate::Expression::LocalVariable(h) => Resolution::Handle(ctx.local_vars[h].ty),

View File

@ -252,7 +252,7 @@ impl Validator {
global_vars: &module.global_variables,
local_vars: &fun.local_variables,
functions: &module.functions,
parameter_types: &fun.parameter_types,
arguments: &fun.arguments,
};
self.typifier
.resolve_all(&fun.expressions, &module.types, &resolve_ctx)?;

View File

@ -73,7 +73,7 @@
workgroup_size: (0, 0, 0),
function: (
name: Some("main"),
parameter_types: [],
arguments: [],
return_type: None,
global_usage: [
(