-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into az-cpr-1727-implement-the-ipfs-hash-algorithm
- Loading branch information
Showing
80 changed files
with
4,020 additions
and
2,337 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
[workspace] | ||
members = [ | ||
"era-compiler-solidity", | ||
"era-yul", | ||
] | ||
resolver = "2" | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,4 @@ | |
//! The Yul IR compiling tools. | ||
//! | ||
|
||
pub mod error; | ||
pub mod lexer; | ||
pub mod parser; |
140 changes: 140 additions & 0 deletions
140
era-compiler-solidity/src/yul/parser/dialect/era/attributes.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
//! | ||
//! Parser of LLVM attributes encoded in the function identifier. | ||
//! | ||
|
||
use std::collections::BTreeSet; | ||
|
||
use era_yul::yul::error::Error as YulError; | ||
use era_yul::yul::parser::error::Error as ParserError; | ||
use era_yul::yul::parser::identifier::Identifier; | ||
|
||
/// The LLVM attribute section prefix. | ||
pub const LLVM_ATTRIBUTE_PREFIX: &str = "$llvm_"; | ||
|
||
/// The LLVM attribute section suffix. | ||
pub const LLVM_ATTRIBUTE_SUFFIX: &str = "_llvm$"; | ||
|
||
/// | ||
/// Gets the list of LLVM attributes provided in the function name. | ||
/// | ||
pub(crate) fn get_llvm_attributes( | ||
identifier: &Identifier, | ||
) -> Result<BTreeSet<era_compiler_llvm_context::Attribute>, YulError> { | ||
let mut valid_attributes = BTreeSet::new(); | ||
|
||
let llvm_begin = identifier.inner.find(LLVM_ATTRIBUTE_PREFIX); | ||
let llvm_end = identifier.inner.find(LLVM_ATTRIBUTE_SUFFIX); | ||
let attribute_string = if let (Some(llvm_begin), Some(llvm_end)) = (llvm_begin, llvm_end) { | ||
if llvm_begin < llvm_end { | ||
&identifier.inner[llvm_begin + LLVM_ATTRIBUTE_PREFIX.len()..llvm_end] | ||
} else { | ||
return Ok(valid_attributes); | ||
} | ||
} else { | ||
return Ok(valid_attributes); | ||
}; | ||
|
||
let mut invalid_attributes = BTreeSet::new(); | ||
for value in attribute_string.split('_') { | ||
match era_compiler_llvm_context::Attribute::try_from(value) { | ||
Ok(attribute) => valid_attributes.insert(attribute), | ||
Err(value) => invalid_attributes.insert(value), | ||
}; | ||
} | ||
|
||
if !invalid_attributes.is_empty() { | ||
return Err(ParserError::InvalidAttributes { | ||
location: identifier.location, | ||
values: invalid_attributes, | ||
} | ||
.into()); | ||
} | ||
|
||
Ok(valid_attributes) | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use std::collections::BTreeSet; | ||
|
||
use era_yul::yul::error::Error as YulError; | ||
use era_yul::yul::lexer::token::location::Location; | ||
use era_yul::yul::parser::error::Error as ParserError; | ||
use era_yul::yul::parser::identifier::Identifier; | ||
|
||
use super::get_llvm_attributes; | ||
|
||
fn identifier_of(name: &str) -> Identifier { | ||
Identifier { | ||
location: Location { line: 0, column: 0 }, | ||
inner: name.to_string(), | ||
r#type: None, | ||
} | ||
} | ||
|
||
fn attribute_helper(s: &&str) -> era_compiler_llvm_context::Attribute { | ||
era_compiler_llvm_context::Attribute::try_from(*s).expect( | ||
"Internal error in test: trying to create an instance of `era_compiler_llvm_context::Attribute` from an invalid string representation.", | ||
) | ||
} | ||
fn immediate_attributes( | ||
representations: &[&str], | ||
) -> BTreeSet<era_compiler_llvm_context::Attribute> { | ||
representations.iter().map(attribute_helper).collect() | ||
} | ||
|
||
#[test] | ||
fn parse_single_attribute() { | ||
let input = r#" | ||
$llvm_Hot_llvm$ | ||
"#; | ||
let expected = immediate_attributes(&["Hot"]); | ||
let result = get_llvm_attributes(&identifier_of(input)).unwrap_or_else(|_| { | ||
panic!( | ||
"LLVM attribute parser should be able to parse a valid input: \"{}\"", | ||
input | ||
) | ||
}); | ||
assert_eq!(result, expected) | ||
} | ||
|
||
#[test] | ||
fn parse_multiple_attributes() { | ||
let input = r#" | ||
$llvm_Hot_Cold_MinSize_llvm$ | ||
"#; | ||
let expected = immediate_attributes(&["Cold", "Hot", "MinSize"]); | ||
let result = get_llvm_attributes(&identifier_of(input)).unwrap_or_else(|_| { | ||
panic!( | ||
"LLVM attribute parser should be able to parse a valid input: \"{}\"", | ||
input | ||
) | ||
}); | ||
assert_eq!(result, expected) | ||
} | ||
#[test] | ||
fn parse_malformed_attributes() { | ||
let input = r#" | ||
$llvm____*&@_llvm$ | ||
"#; | ||
get_llvm_attributes(&identifier_of(input)).expect_err(&format!( | ||
"LLVM attributes parser should not parse attributes from the malformed input \"{}\"", | ||
input | ||
)); | ||
} | ||
|
||
#[test] | ||
fn parse_invalid_attributes() { | ||
let input = r#" | ||
$llvm_Hot_Cold_MinSize_BogusAttr_llvm$ | ||
"#; | ||
|
||
let values = BTreeSet::from(["BogusAttr".into()]); | ||
let location = Location { line: 0, column: 0 }; | ||
let expected = YulError::Parser(ParserError::InvalidAttributes { location, values }); | ||
let result = get_llvm_attributes(&identifier_of(input)) | ||
.expect_err("LLVM attributes parser should not mask unknown attributes"); | ||
|
||
assert_eq!(result, expected); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
//! | ||
//! LLVM-specific part of the parser. | ||
//! | ||
|
||
pub mod attributes; | ||
|
||
use std::collections::BTreeSet; | ||
|
||
use era_yul::yul::error::Error; | ||
use era_yul::yul::lexer::token::location::Location; | ||
use era_yul::yul::lexer::Lexer; | ||
use era_yul::yul::parser::error::Error as ParserError; | ||
use era_yul::yul::parser::identifier::Identifier; | ||
|
||
use self::attributes::get_llvm_attributes; | ||
|
||
use era_yul::yul::parser::dialect::Dialect; | ||
|
||
/// Era-specific part of the parser. | ||
#[derive(serde::Serialize, serde::Deserialize, PartialEq, Eq, Clone, Debug)] | ||
pub struct EraDialect {} | ||
|
||
impl Dialect for EraDialect { | ||
type FunctionAttribute = era_compiler_llvm_context::Attribute; | ||
|
||
fn extract_attributes( | ||
identifier: &Identifier, | ||
_: &mut Lexer, | ||
) -> Result<BTreeSet<Self::FunctionAttribute>, era_yul::yul::error::Error> { | ||
get_llvm_attributes(identifier) | ||
} | ||
|
||
fn sanitize_function( | ||
identifier: &Identifier, | ||
arguments: &mut Vec<Identifier>, | ||
location: Location, | ||
_lexer: &mut Lexer, | ||
) -> Result<(), Error> { | ||
if identifier | ||
.inner | ||
.contains(era_compiler_llvm_context::EraVMFunction::ZKSYNC_NEAR_CALL_ABI_PREFIX) | ||
{ | ||
if arguments.is_empty() { | ||
return Err(ParserError::InvalidNumberOfArguments { | ||
location, | ||
identifier: identifier.inner.clone(), | ||
expected: 1, | ||
found: arguments.len(), | ||
} | ||
.into()); | ||
} | ||
|
||
arguments.remove(0); | ||
} | ||
if identifier.inner.contains( | ||
era_compiler_llvm_context::EraVMFunction::ZKSYNC_NEAR_CALL_ABI_EXCEPTION_HANDLER, | ||
) && !arguments.is_empty() | ||
{ | ||
return Err(ParserError::InvalidNumberOfArguments { | ||
location, | ||
identifier: identifier.inner.clone(), | ||
expected: 0, | ||
found: arguments.len(), | ||
} | ||
.into()); | ||
} | ||
Ok(()) | ||
} | ||
} |
Oops, something went wrong.