mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-05 23:33:07 +00:00
Add %rep syntax for repeating a block
Same syntax as NASM.
This commit is contained in:
parent
8751aaec7a
commit
6d69e14a89
@ -9,18 +9,21 @@
|
|||||||
%endmacro
|
%endmacro
|
||||||
|
|
||||||
%macro pop2
|
%macro pop2
|
||||||
pop
|
%rep 2
|
||||||
pop
|
pop
|
||||||
|
%endrep
|
||||||
%endmacro
|
%endmacro
|
||||||
|
|
||||||
%macro pop3
|
%macro pop3
|
||||||
pop
|
%rep 3
|
||||||
%pop2
|
pop
|
||||||
|
%endrep
|
||||||
%endmacro
|
%endmacro
|
||||||
|
|
||||||
%macro pop4
|
%macro pop4
|
||||||
%pop2
|
%rep 4
|
||||||
%pop2
|
pop
|
||||||
|
%endrep
|
||||||
%endmacro
|
%endmacro
|
||||||
|
|
||||||
// If pred is zero, yields z; otherwise, yields nz
|
// If pred is zero, yields z; otherwise, yields nz
|
||||||
|
|||||||
@ -44,6 +44,7 @@ pub(crate) fn assemble(files: Vec<File>, constants: HashMap<String, U256>) -> Ke
|
|||||||
let mut local_labels = Vec::with_capacity(files.len());
|
let mut local_labels = Vec::with_capacity(files.len());
|
||||||
for file in files {
|
for file in files {
|
||||||
let expanded_file = expand_macros(file.body, ¯os);
|
let expanded_file = expand_macros(file.body, ¯os);
|
||||||
|
let expanded_file = expand_repeats(expanded_file);
|
||||||
let expanded_file = inline_constants(expanded_file, &constants);
|
let expanded_file = inline_constants(expanded_file, &constants);
|
||||||
local_labels.push(find_labels(&expanded_file, &mut offset, &mut global_labels));
|
local_labels.push(find_labels(&expanded_file, &mut offset, &mut global_labels));
|
||||||
expanded_files.push(expanded_file);
|
expanded_files.push(expanded_file);
|
||||||
@ -132,6 +133,21 @@ fn expand_macro_call(
|
|||||||
expand_macros(expanded_item, macros)
|
expand_macros(expanded_item, macros)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn expand_repeats(body: Vec<Item>) -> Vec<Item> {
|
||||||
|
let mut expanded = vec![];
|
||||||
|
for item in body {
|
||||||
|
if let Item::Repeat(count, block) = item {
|
||||||
|
let reps = count.to_u256().as_usize();
|
||||||
|
for _ in 0..reps {
|
||||||
|
expanded.extend(block.clone());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
expanded.push(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expanded
|
||||||
|
}
|
||||||
|
|
||||||
fn inline_constants(body: Vec<Item>, constants: &HashMap<String, U256>) -> Vec<Item> {
|
fn inline_constants(body: Vec<Item>, constants: &HashMap<String, U256>) -> Vec<Item> {
|
||||||
body.into_iter()
|
body.into_iter()
|
||||||
.map(|item| {
|
.map(|item| {
|
||||||
@ -157,8 +173,8 @@ fn find_labels(
|
|||||||
let mut local_labels = HashMap::<String, usize>::new();
|
let mut local_labels = HashMap::<String, usize>::new();
|
||||||
for item in body {
|
for item in body {
|
||||||
match item {
|
match item {
|
||||||
Item::MacroDef(_, _, _) | Item::MacroCall(_, _) => {
|
Item::MacroDef(_, _, _) | Item::MacroCall(_, _) | Item::Repeat(_, _) => {
|
||||||
panic!("Macros should have been expanded already")
|
panic!("Macros and repeats should have been expanded already")
|
||||||
}
|
}
|
||||||
Item::GlobalLabelDeclaration(label) => {
|
Item::GlobalLabelDeclaration(label) => {
|
||||||
let old = global_labels.insert(label.clone(), *offset);
|
let old = global_labels.insert(label.clone(), *offset);
|
||||||
@ -185,8 +201,8 @@ fn assemble_file(
|
|||||||
// Assemble the file.
|
// Assemble the file.
|
||||||
for item in body {
|
for item in body {
|
||||||
match item {
|
match item {
|
||||||
Item::MacroDef(_, _, _) | Item::MacroCall(_, _) => {
|
Item::MacroDef(_, _, _) | Item::MacroCall(_, _) | Item::Repeat(_, _) => {
|
||||||
panic!("Macros should have been expanded already")
|
panic!("Macros and repeats should have been expanded already")
|
||||||
}
|
}
|
||||||
Item::GlobalLabelDeclaration(_) | Item::LocalLabelDeclaration(_) => {
|
Item::GlobalLabelDeclaration(_) | Item::LocalLabelDeclaration(_) => {
|
||||||
// Nothing to do; we processed labels in the prior phase.
|
// Nothing to do; we processed labels in the prior phase.
|
||||||
@ -393,6 +409,13 @@ mod tests {
|
|||||||
assert_eq!(kernel.code, vec![push4, 0xDE, 0xAD, 0xBE, 0xEF]);
|
assert_eq!(kernel.code, vec![push4, 0xDE, 0xAD, 0xBE, 0xEF]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn repeat() {
|
||||||
|
let kernel = parse_and_assemble(&["%rep 3 ADD %endrep"]);
|
||||||
|
let add = get_opcode("ADD");
|
||||||
|
assert_eq!(kernel.code, vec![add, add, add]);
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_and_assemble(files: &[&str]) -> Kernel {
|
fn parse_and_assemble(files: &[&str]) -> Kernel {
|
||||||
parse_and_assemble_with_constants(files, HashMap::new())
|
parse_and_assemble_with_constants(files, HashMap::new())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,6 +12,8 @@ pub(crate) enum Item {
|
|||||||
MacroDef(String, Vec<String>, Vec<Item>),
|
MacroDef(String, Vec<String>, Vec<Item>),
|
||||||
/// Calls a macro: name, args.
|
/// Calls a macro: name, args.
|
||||||
MacroCall(String, Vec<PushTarget>),
|
MacroCall(String, Vec<PushTarget>),
|
||||||
|
/// Repetition, like `%rep` in NASM.
|
||||||
|
Repeat(Literal, Vec<Item>),
|
||||||
/// Declares a global label.
|
/// Declares a global label.
|
||||||
GlobalLabelDeclaration(String),
|
GlobalLabelDeclaration(String),
|
||||||
/// Declares a label that is local to the current file.
|
/// Declares a label that is local to the current file.
|
||||||
|
|||||||
@ -15,9 +15,10 @@ literal = { literal_hex | literal_decimal }
|
|||||||
variable = ${ "$" ~ identifier }
|
variable = ${ "$" ~ identifier }
|
||||||
constant = ${ "@" ~ identifier }
|
constant = ${ "@" ~ identifier }
|
||||||
|
|
||||||
item = { macro_def | macro_call | global_label | local_label | bytes_item | push_instruction | nullary_instruction }
|
item = { macro_def | macro_call | repeat | global_label | local_label | bytes_item | push_instruction | nullary_instruction }
|
||||||
macro_def = { ^"%macro" ~ identifier ~ macro_paramlist? ~ item* ~ ^"%endmacro" }
|
macro_def = { ^"%macro" ~ identifier ~ macro_paramlist? ~ item* ~ ^"%endmacro" }
|
||||||
macro_call = ${ "%" ~ !(^"macro" | ^"endmacro") ~ identifier ~ macro_arglist? }
|
macro_call = ${ "%" ~ !(^"macro" | ^"endmacro" | ^"rep" | ^"endrep") ~ identifier ~ macro_arglist? }
|
||||||
|
repeat = { ^"%rep" ~ literal ~ item* ~ ^"%endrep" }
|
||||||
macro_paramlist = { "(" ~ identifier ~ ("," ~ identifier)* ~ ")" }
|
macro_paramlist = { "(" ~ identifier ~ ("," ~ identifier)* ~ ")" }
|
||||||
macro_arglist = !{ "(" ~ push_target ~ ("," ~ push_target)* ~ ")" }
|
macro_arglist = !{ "(" ~ push_target ~ ("," ~ push_target)* ~ ")" }
|
||||||
global_label = { ^"GLOBAL " ~ identifier ~ ":" }
|
global_label = { ^"GLOBAL " ~ identifier ~ ":" }
|
||||||
|
|||||||
@ -23,6 +23,7 @@ fn parse_item(item: Pair<Rule>) -> Item {
|
|||||||
match item.as_rule() {
|
match item.as_rule() {
|
||||||
Rule::macro_def => parse_macro_def(item),
|
Rule::macro_def => parse_macro_def(item),
|
||||||
Rule::macro_call => parse_macro_call(item),
|
Rule::macro_call => parse_macro_call(item),
|
||||||
|
Rule::repeat => parse_repeat(item),
|
||||||
Rule::global_label => {
|
Rule::global_label => {
|
||||||
Item::GlobalLabelDeclaration(item.into_inner().next().unwrap().as_str().into())
|
Item::GlobalLabelDeclaration(item.into_inner().next().unwrap().as_str().into())
|
||||||
}
|
}
|
||||||
@ -70,6 +71,13 @@ fn parse_macro_call(item: Pair<Rule>) -> Item {
|
|||||||
Item::MacroCall(name, args)
|
Item::MacroCall(name, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_repeat(item: Pair<Rule>) -> Item {
|
||||||
|
assert_eq!(item.as_rule(), Rule::repeat);
|
||||||
|
let mut inner = item.into_inner().peekable();
|
||||||
|
let count = parse_literal(inner.next().unwrap());
|
||||||
|
Item::Repeat(count, inner.map(parse_item).collect())
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_push_target(target: Pair<Rule>) -> PushTarget {
|
fn parse_push_target(target: Pair<Rule>) -> PushTarget {
|
||||||
assert_eq!(target.as_rule(), Rule::push_target);
|
assert_eq!(target.as_rule(), Rule::push_target);
|
||||||
let inner = target.into_inner().next().unwrap();
|
let inner = target.into_inner().next().unwrap();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user