Skip to content

Commit

Permalink
Support specifying inputs and outputs for code sections
Browse files Browse the repository at this point in the history
  • Loading branch information
gumb0 committed May 26, 2024
1 parent 460130e commit 33d6f10
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 40 deletions.
30 changes: 26 additions & 4 deletions etk-asm/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,8 @@ impl Assembler {
#[derive(Clone, Copy, Debug, PartialEq)]
struct EOFCodeSection {
size: u16,
inputs: u8,
outputs: u8,
max_stack_height: u16,
}

Expand All @@ -591,9 +593,16 @@ impl Assembler {
for section_bounds in self.sections.windows(2) {
if let [start, end] = section_bounds {
let size = (end.position - start.position) as u16;
if let EOFSectionKind::Code { max_stack_height } = start.kind {
if let EOFSectionKind::Code {
inputs,
outputs,
max_stack_height,
} = start.kind
{
code_sections.push(EOFCodeSection {
size,
inputs,
outputs,
max_stack_height,
});
} else {
Expand All @@ -605,9 +614,16 @@ impl Assembler {
// add last section
if let Some(&last_section) = self.sections.last() {
let size = (self.concrete_len - last_section.position) as u16;
if let EOFSectionKind::Code { max_stack_height } = last_section.kind {
if let EOFSectionKind::Code {
inputs,
outputs,
max_stack_height,
} = last_section.kind
{
code_sections.push(EOFCodeSection {
size,
inputs,
outputs,
max_stack_height,
});
} else {
Expand Down Expand Up @@ -636,8 +652,8 @@ impl Assembler {
output.push(0x00);
// types section
for code_section in code_sections {
// TODO all functions are 0 inputs, non-returning for now
output.extend_from_slice(&[0x00, 0x80]);
output.push(code_section.inputs);
output.push(code_section.outputs);
output.extend_from_slice(&code_section.max_stack_height.to_be_bytes());
}
Ok(())
Expand Down Expand Up @@ -1666,6 +1682,8 @@ mod tests {
AbstractOp::new(Push0),
AbstractOp::new(Stop),
AbstractOp::EOFSection(EOFSectionKind::Code {
inputs: 0,
outputs: 0,
max_stack_height: 0,
}),
AbstractOp::new(Stop),
Expand All @@ -1682,13 +1700,17 @@ mod tests {

let code = vec![
AbstractOp::EOFSection(EOFSectionKind::Code {
inputs: 0,
outputs: 0x80,
max_stack_height: 1,
}),
AbstractOp::new(Push0),
AbstractOp::new(Stop),
AbstractOp::EOFSection(EOFSectionKind::Data),
AbstractOp::new(JumpDest),
AbstractOp::EOFSection(EOFSectionKind::Code {
inputs: 0,
outputs: 0,
max_stack_height: 0,
}),
AbstractOp::new(Stop),
Expand Down
4 changes: 4 additions & 0 deletions etk-asm/src/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,10 @@ impl Access {
pub enum EOFSectionKind {
/// Code section
Code {
/// Code section's inputs
inputs: u8,
/// Code section's outputs or 0x80 if secton is non-returning
outputs: u8,
/// Code section's max stack height
max_stack_height: u16,
},
Expand Down
6 changes: 5 additions & 1 deletion etk-asm/src/parse/asm.pest
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,12 @@ function_parameter = @{ ASCII_ALPHA ~ ASCII_ALPHANUMERIC* }
//////////////
section = ${ "section" ~ WHITESPACE ~ section_kind ~ (WHITESPACE ~ section_attributes)? }
section_kind = { ".code" | ".data" }
section_attributes = { max_stack_height_attribute? }
section_attributes = { (section_attribute ~WHITESPACE?)* }
section_attribute = { inputs_attribute | outputs_attribute | max_stack_height_attribute }
max_stack_height_attribute = { "max_stack_height" ~ "=" ~ number }
inputs_attribute = { "inputs" ~ "=" ~ number }
outputs_attribute = { "outputs" ~ "=" ~ (number | nonreturning) }
nonreturning = { "nonret" }

//////////////
// operands //
Expand Down
72 changes: 44 additions & 28 deletions etk-asm/src/parse/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ mod expression;
mod macros;

pub(crate) mod error;

mod parser {
#![allow(clippy::upper_case_acronyms)]

Expand Down Expand Up @@ -54,34 +55,7 @@ fn parse_abstract_op(pair: Pair<Rule>) -> Result<AbstractOp, ParseError> {
let op = Op::new(spec).unwrap();
AbstractOp::Op(op)
}
Rule::section => {
let mut pairs = pair.into_inner();
let section_kind = pairs.next().unwrap().as_str();

if section_kind == ".code" {
let max_stack_height = {
if let Some(section_attributes) = pairs.next() {
if let Some(msh_pair) = section_attributes.into_inner().next() {
msh_pair
.into_inner()
.next()
.unwrap()
.as_str()
.parse::<u16>()
.unwrap()
} else {
0
}
} else {
0
}
};
AbstractOp::EOFSection(EOFSectionKind::Code { max_stack_height })
} else {
// attributes are ignored
AbstractOp::EOFSection(EOFSectionKind::Data)
}
}
Rule::section => parse_section(pair)?,
_ => unreachable!(),
};

Expand All @@ -107,6 +81,48 @@ fn parse_push(pair: Pair<Rule>) -> Result<AbstractOp, ParseError> {
Ok(AbstractOp::Op(spec.with(expr).unwrap()))
}

fn parse_section(pair: Pair<Rule>) -> Result<AbstractOp, ParseError> {
let mut pairs = pair.into_inner();
let section_kind = pairs.next().unwrap().as_str();

if section_kind == ".code" {
let mut inputs: u8 = 0;
let mut outputs: u8 = 0x80; // non-returning by default
let mut max_stack_height: u16 = 0;
if let Some(section_attributes) = pairs.next() {
for attribute in section_attributes.into_inner() {
let attr_inner = attribute.into_inner().next().unwrap();

match attr_inner.as_rule() {
Rule::max_stack_height_attribute => {
let max_stack_height_str = attr_inner.into_inner().next().unwrap().as_str();
max_stack_height = max_stack_height_str.parse::<u16>().unwrap();
}
Rule::inputs_attribute => {
let inputs_str = attr_inner.into_inner().next().unwrap().as_str();
inputs = inputs_str.parse::<u8>().unwrap();
}
Rule::outputs_attribute => {
let outputs_str = attr_inner.into_inner().next().unwrap().as_str();
if outputs_str != "nonret" {
outputs = outputs_str.parse::<u8>().unwrap();
}
}
_ => unreachable!(),
}
}
}
Ok(AbstractOp::EOFSection(EOFSectionKind::Code {
inputs,
outputs,
max_stack_height,
}))
} else {
// attributes are ignored
Ok(AbstractOp::EOFSection(EOFSectionKind::Data))
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
5 changes: 1 addition & 4 deletions etk-asm/tests/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,10 +369,7 @@ fn test_eof_multiple_code_sections() -> Result<(), Error> {
let mut ingester = Ingest::new(&mut output);
ingester.ingest_file(source(&["eof", "main2.etk"]))?;

assert_eq!(
output,
hex!("ef0001 01000c 020003000100010003 040000 00 00800000 00800000 00800002 00 fe 5f5ff3")
);
assert_eq!(output, hex!("ef0001 010010 0200040001000100030004 040000 00 00800000 00800000 00800002 01000002 00 fe 5f5ff3 505f5f00"));

Ok(())
}
Expand Down
12 changes: 9 additions & 3 deletions etk-asm/tests/asm/eof/main2.etk
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
section .code
stop

section .code
section .code outputs=nonret
invalid

section .code max_stack_height=2
section .code outputs=nonret max_stack_height=2
push0
push0
return

section .code inputs=1 outputs=0 max_stack_height=2
pop
push0
push0
return
stop

0 comments on commit 33d6f10

Please sign in to comment.