Statement for void function call

This commit is contained in:
Dzmitry Malyshau
2021-02-05 10:54:50 -05:00
committed by Dzmitry Malyshau
parent f9f41fc9bf
commit d949d58f7b
12 changed files with 668 additions and 621 deletions

View File

@@ -979,11 +979,11 @@ impl<'a, W: Write> Writer<'a, W> {
// The indentation is only for readability
write!(self.out, "{}", INDENT.repeat(indent))?;
match sta {
match *sta {
// Blocks are simple we just need to write the block statements between braces
// We could also just print the statements but this is more readable and maps more
// closely to the IR
Statement::Block(block) => {
Statement::Block(ref block) => {
writeln!(self.out, "{{")?;
for sta in block.iter() {
// Increase the indentation to help with readability
@@ -1001,11 +1001,11 @@ impl<'a, W: Write> Writer<'a, W> {
// ```
Statement::If {
condition,
accept,
reject,
ref accept,
ref reject,
} => {
write!(self.out, "if(")?;
self.write_expr(*condition, ctx)?;
self.write_expr(condition, ctx)?;
writeln!(self.out, ") {{")?;
for sta in accept {
@@ -1044,12 +1044,12 @@ impl<'a, W: Write> Writer<'a, W> {
// so that we don't need to print a `break` for it
Statement::Switch {
selector,
cases,
default,
ref cases,
ref default,
} => {
// Start the switch
write!(self.out, "switch(")?;
self.write_expr(*selector, ctx)?;
self.write_expr(selector, ctx)?;
writeln!(self.out, ") {{")?;
// Write all cases
@@ -1091,7 +1091,10 @@ impl<'a, W: Write> Writer<'a, W> {
// continuing
// }
// ```
Statement::Loop { body, continuing } => {
Statement::Loop {
ref body,
ref continuing,
} => {
writeln!(self.out, "while(true) {{")?;
for sta in body.iter().chain(continuing.iter()) {
@@ -1111,7 +1114,7 @@ impl<'a, W: Write> Writer<'a, W> {
// Write the expression to be returned if needed
if let Some(expr) = value {
write!(self.out, " ")?;
self.write_expr(*expr, ctx)?;
self.write_expr(expr, ctx)?;
}
writeln!(self.out, ";")?;
}
@@ -1121,11 +1124,20 @@ impl<'a, W: Write> Writer<'a, W> {
Statement::Kill => writeln!(self.out, "discard;")?,
// Stores in glsl are just variable assignments written as `pointer = value;`
Statement::Store { pointer, value } => {
self.write_expr(*pointer, ctx)?;
self.write_expr(pointer, ctx)?;
write!(self.out, " = ")?;
self.write_expr(*value, ctx)?;
self.write_expr(value, ctx)?;
writeln!(self.out, ";")?
}
// A `Call` is written `name(arguments)` where `arguments` is a comma separated expressions list
Statement::Call {
function,
ref arguments,
} => {
write!(self.out, "{}(", &self.names[&NameKey::Function(function)])?;
self.write_slice(arguments, |this, _, arg| this.write_expr(*arg, ctx))?;
write!(self.out, ");")?
}
}
Ok(())

View File

@@ -741,6 +741,15 @@ impl<W: Write> Writer<W> {
self.put_expression(value, context)?;
writeln!(self.out, ";")?;
}
crate::Statement::Call {
function,
ref arguments,
} => {
let name = &self.names[&NameKey::Function(function)];
write!(self.out, "{}", name)?;
self.put_call("", arguments, context)?;
writeln!(self.out, ";")?;
}
}
}
Ok(())

View File

@@ -181,7 +181,7 @@ pub struct Writer {
debugs: Vec<Instruction>,
annotations: Vec<Instruction>,
flags: WriterFlags,
void_type: Option<u32>,
void_type: u32,
lookup_type: crate::FastHashMap<LookupType, Word>,
lookup_function: crate::FastHashMap<crate::Handle<crate::Function>, Word>,
lookup_function_type: crate::FastHashMap<LookupFunctionType, Word>,
@@ -209,19 +209,19 @@ impl Writer {
Writer {
physical_layout: PhysicalLayout::new(header),
logical_layout: LogicalLayout::default(),
id_count: 0,
id_count: 2, // 0 is void type, 1 is the GLSL ext inst
capabilities,
debugs: vec![],
annotations: vec![],
flags,
void_type: None,
void_type: 0,
lookup_type: crate::FastHashMap::default(),
lookup_function: crate::FastHashMap::default(),
lookup_function_type: crate::FastHashMap::default(),
lookup_constant: crate::FastHashMap::default(),
lookup_global_variable: crate::FastHashMap::default(),
struct_type_handles: crate::FastHashMap::default(),
gl450_ext_inst_id: 0,
gl450_ext_inst_id: 1,
layouter: Layouter::default(),
typifier: Typifier::new(),
}
@@ -295,26 +295,6 @@ impl Writer {
})
}
fn get_function_return_type(
&mut self,
ty: Option<crate::Handle<crate::Type>>,
arena: &crate::Arena<crate::Type>,
) -> Result<Word, Error> {
match ty {
Some(handle) => self.get_type_id(arena, LookupType::Handle(handle)),
None => Ok(match self.void_type {
Some(id) => id,
None => {
let id = self.generate_id();
self.void_type = Some(id);
super::instructions::instruction_type_void(id)
.to_words(&mut self.logical_layout.declarations);
id
}
}),
}
}
fn get_pointer_id(
&mut self,
arena: &crate::Arena<crate::Type>,
@@ -415,8 +395,10 @@ impl Writer {
.insert(handle, LocalVariable { id, instruction });
}
let return_type_id =
self.get_function_return_type(ir_function.return_type, &ir_module.types)?;
let return_type_id = match ir_function.return_type {
Some(handle) => self.get_type_id(&ir_module.types, LookupType::Handle(handle))?,
None => self.void_type,
};
let mut parameter_type_ids = Vec::with_capacity(ir_function.arguments.len());
for argument in ir_function.arguments.iter() {
@@ -1922,6 +1904,10 @@ impl Writer {
block = Block::new(merge_id);
}
crate::Statement::Switch { .. } => {
log::error!("unimplemented Switch");
return Err(Error::FeatureNotImplemented("switch"));
}
crate::Statement::Loop {
ref body,
ref continuing,
@@ -2007,9 +1993,33 @@ impl Writer {
pointer_id, value_id, None,
));
}
_ => {
log::error!("unimplemented {:?}", statement);
return Err(Error::FeatureNotImplemented("statement"));
crate::Statement::Call {
function: local_function,
ref arguments,
} => {
let id = self.generate_id();
//TODO: avoid heap allocation
let mut argument_ids = vec![];
for argument in arguments {
let arg_id = self.write_expression(
ir_module,
ir_function,
*argument,
&mut block,
function,
)?;
argument_ids.push(arg_id);
}
block
.body
.push(super::instructions::instruction_function_call(
self.void_type,
id,
*self.lookup_function.get(&local_function).unwrap(),
argument_ids.as_slice(),
));
}
}
}
@@ -2030,7 +2040,8 @@ impl Writer {
}
fn write_logical_layout(&mut self, ir_module: &crate::Module) -> Result<(), Error> {
self.gl450_ext_inst_id = self.generate_id();
super::instructions::instruction_type_void(self.void_type)
.to_words(&mut self.logical_layout.declarations);
super::instructions::instruction_ext_inst_import(self.gl450_ext_inst_id, "GLSL.std.450")
.to_words(&mut self.logical_layout.ext_inst_imports);
@@ -2113,9 +2124,9 @@ mod tests {
fn test_writer_generate_id() {
let mut writer = create_writer();
assert_eq!(writer.id_count, 0);
assert_eq!(writer.id_count, 2);
writer.generate_id();
assert_eq!(writer.id_count, 1);
assert_eq!(writer.id_count, 3);
}
#[test]
@@ -2123,7 +2134,7 @@ mod tests {
let mut writer = create_writer();
assert_eq!(writer.physical_layout.bound, 0);
writer.write_physical_layout();
assert_eq!(writer.physical_layout.bound, 1);
assert_eq!(writer.physical_layout.bound, 3);
}
fn create_writer() -> Writer {

View File

@@ -802,6 +802,11 @@ pub enum Statement {
pointer: Handle<Expression>,
value: Handle<Expression>,
},
/// Calls a function with no return value.
Call {
function: Handle<Function>,
arguments: Vec<Handle<Expression>>,
},
}
/// A function argument.

View File

@@ -203,6 +203,15 @@ where
self.visitor.visit_lhs_expr(&self.expressions[left]);
self.traverse_expr(value);
}
S::Call {
function,
ref arguments,
} => {
for &argument in arguments {
self.traverse_expr(argument);
}
self.visitor.visit_fun(function);
}
}
}
}

View File

@@ -35,6 +35,7 @@ pub fn ensure_block_returns(block: &mut crate::Block) {
| Some(&mut crate::Statement::Kill) => (),
Some(&mut crate::Statement::Loop { .. })
| Some(&mut crate::Statement::Store { .. })
| Some(&mut crate::Statement::Call { .. })
| None => block.push(crate::Statement::Return { value: None }),
}
}