Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ssa_refactor)!: Add Slices #1728

Merged
merged 60 commits into from
Jul 7, 2023
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
913bc9b
initial slices work on frontend
vezenovm Jun 16, 2023
5ec2c67
cargo clippy
vezenovm Jun 16, 2023
8a6f188
develop comment cleanup
vezenovm Jun 16, 2023
cf309a0
working push_back and len slices commands
vezenovm Jun 16, 2023
b442f88
cargo clippy
vezenovm Jun 16, 2023
5934644
cleanup
vezenovm Jun 16, 2023
f9d7921
fix clippy
vezenovm Jun 16, 2023
c253625
empty slice being processed
vezenovm Jun 16, 2023
990121e
cargo clippy
vezenovm Jun 16, 2023
2070e5e
Merge branch 'master' into mv/slices-2
vezenovm Jun 16, 2023
6717d9d
delete old comment
vezenovm Jun 16, 2023
8f17fda
remove unused import
vezenovm Jun 16, 2023
3366bb9
add enable_slices flag to avoid slices in old SSA
vezenovm Jun 16, 2023
c8dd8cd
add new SSA type for slices
vezenovm Jun 16, 2023
88261b3
missing Slice conversion
vezenovm Jun 16, 2023
0f3e9fd
Update crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs
vezenovm Jun 16, 2023
e5e8eef
PR comments, fix slice/array subtyping
vezenovm Jul 3, 2023
fe29949
origin merge
vezenovm Jul 3, 2023
0f3fa79
hack to handle duplicate methods and mismatched types when compiling …
vezenovm Jul 3, 2023
fdd3266
cleanup enable_slices tech debt to be part of the NodeInterner
vezenovm Jul 3, 2023
18061d8
reference enable_slices flag issue
vezenovm Jul 3, 2023
1de2354
cleanup name
vezenovm Jul 3, 2023
eecd581
remove SSA Value::Slice
vezenovm Jul 3, 2023
b4960f9
merge master and use simplify_call method
vezenovm Jul 3, 2023
cc04a7a
remove dbg
vezenovm Jul 3, 2023
c5d9d9c
fix array len from slice params
vezenovm Jul 4, 2023
0be7871
remove old debug
vezenovm Jul 4, 2023
525cfd6
unwrap_array_element_type method in monomorphization pass
vezenovm Jul 4, 2023
a8033c8
cargo clippy
vezenovm Jul 4, 2023
b33dea2
mark issue in TODO comment for tech debt that removes slice module in…
vezenovm Jul 4, 2023
bc49ec3
Update crates/noirc_evaluator/src/ssa_refactor/ir/instruction.rs
vezenovm Jul 4, 2023
a51d70d
fix stdlib crate check
vezenovm Jul 4, 2023
901c973
Update noir_stdlib/src/slice.nr
vezenovm Jul 4, 2023
8fe073b
Update noir_stdlib/src/slice.nr
vezenovm Jul 4, 2023
64ecced
Update noir_stdlib/src/slice.nr
vezenovm Jul 4, 2023
2d14285
Update noir_stdlib/src/slice.nr
vezenovm Jul 4, 2023
5d8151f
PR comments and stdlib crate assert
vezenovm Jul 4, 2023
99bd62c
master merge
vezenovm Jul 4, 2023
b6fd1b8
Merge remote-tracking branch 'origin/mv/slices-2' into mv/slices-2
vezenovm Jul 4, 2023
dd3be16
cargo fmt
vezenovm Jul 4, 2023
b7f4bb2
keep enable slices check in expr type check
vezenovm Jul 5, 2023
4344361
increase timeout time
vezenovm Jul 5, 2023
f2b9cbb
increase timeout to 60m
vezenovm Jul 5, 2023
c47f7fb
back to 30m timeout
vezenovm Jul 5, 2023
ebf36fb
excldue 6_array from old ssa test and move 6_array into ssa_refactor …
vezenovm Jul 5, 2023
8493267
merge conflicts w/ master
vezenovm Jul 5, 2023
2938b47
unwrap_or_else for first_elem_type
vezenovm Jul 5, 2023
fa29eb4
only test new ssa :D
vezenovm Jul 6, 2023
34d6755
add back old ssa tests
vezenovm Jul 6, 2023
f0d0539
remove Vec type
vezenovm Jul 6, 2023
cd25582
remove Vec type check
vezenovm Jul 6, 2023
5e6bf97
Merge branch 'master' into mv/slices-2
vezenovm Jul 6, 2023
691a35b
remove Vec from stdlib as we have no primitive type until we add in V…
vezenovm Jul 6, 2023
f0f0a71
try w/ a pub input to 6_array
vezenovm Jul 6, 2023
b55a45a
im dumb and misplaced the pub
vezenovm Jul 6, 2023
80d28e0
master merge after no more driver
vezenovm Jul 7, 2023
b746a96
remove pub
vezenovm Jul 7, 2023
daac684
temp: remove unused tests for debugging
kevaundray Jul 7, 2023
6d1a45b
Revert "temp: remove unused tests for debugging"
kevaundray Jul 7, 2023
49c7610
Merge branch 'master' into mv/slices-2
jfecher Jul 7, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[package]
authors = [""]
compiler_version = "0.6.0"

[dependencies]
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
x = "5"
y = "10"
21 changes: 21 additions & 0 deletions crates/nargo_cli/tests/test_data_ssa_refactor/slices/src/main.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use dep::std::slice;

fn main(x : Field, y : pub Field) {

let mut slice: [Field] = [0; 2];

assert(slice[0] == 0);
assert(slice[0] != 1);

let slice_plus_10 = slice.push_back(10);
assert(slice_plus_10[2] == 10);
assert(slice_plus_10[2] != 8);
assert(slice_plus_10.len() == 3);

let mut new_slice: [Field] = [];
jfecher marked this conversation as resolved.
Show resolved Hide resolved
for i in 0..5 {
new_slice = new_slice.push_back(0);
}
assert(new_slice.len() == 5);
}

1 change: 1 addition & 0 deletions crates/noirc_evaluator/src/ssa/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1211,6 +1211,7 @@ impl SsaContext {
Type::Function(..) => ObjectType::Function,
Type::Tuple(_) => todo!("Conversion to ObjectType is unimplemented for tuples"),
Type::String(_) => todo!("Conversion to ObjectType is unimplemented for strings"),
Type::Slice(_) => todo!("Conversion to ObjectType is unimplemented for slices"),
Type::Vec(_) => todo!("Conversion to ObjectType is unimplemented for Vecs"),
}
}
Expand Down
1 change: 1 addition & 0 deletions crates/noirc_evaluator/src/ssa/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ impl Value {
Type::Unit
| Type::Function(..)
| Type::Array(..)
| Type::Slice(..)
| Type::Vec(..)
| Type::String(..)
| Type::Integer(..)
Expand Down
15 changes: 15 additions & 0 deletions crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,11 @@ impl Context {
let elements = array.iter().map(|element| self.convert_value(*element, dfg));
AcirValue::Array(elements.collect())
}
Value::Slice { array: initial_array, .. } => {
let elements =
initial_array.iter().map(|element| self.convert_value(*element, dfg));
vezenovm marked this conversation as resolved.
Show resolved Hide resolved
AcirValue::Array(elements.collect())
}
Value::Intrinsic(..) => todo!(),
Value::Function(..) => unreachable!("ICE: All functions should have been inlined"),
Value::Instruction { .. } | Value::Param { .. } => {
Expand Down Expand Up @@ -581,6 +586,16 @@ impl Context {
}
Vec::new()
}
// Intrinsic::SlicePushBack => {
// let mut slice = self.convert_array_value(arguments[0], dfg);
// let elem = self.convert_value(arguments[1], dfg);

// dbg!(slice.clone());
// dbg!(elem.clone());
// dbg!(self.convert_value(result_ids[0], dfg));
// slice.push_back(elem);
// vec![AcirValue::Array(slice)]
// }
_ => todo!("expected a black box function"),
jfecher marked this conversation as resolved.
Show resolved Hide resolved
}
}
Expand Down
26 changes: 23 additions & 3 deletions crates/noirc_evaluator/src/ssa_refactor/ir/dfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,17 @@ impl DataFlowGraph {
self.make_value(Value::Array { array, element_type })
}

/// Create a new slice value from the given elements
/// This is the initial slice for which the length will change
/// during program execution
pub(crate) fn make_slice(
&mut self,
array: im::Vector<ValueId>,
element_type: Rc<CompositeType>,
) -> ValueId {
self.make_value(Value::Slice { array, element_type })
}

/// Gets or creates a ValueId for the given FunctionId.
pub(crate) fn import_function(&mut self, function: FunctionId) -> ValueId {
if let Some(existing) = self.functions.get(&function) {
Expand All @@ -205,10 +216,16 @@ impl DataFlowGraph {

/// Gets or creates a ValueId for the given Intrinsic.
pub(crate) fn import_intrinsic(&mut self, intrinsic: Intrinsic) -> ValueId {
if let Some(existing) = self.intrinsics.get(&intrinsic) {
if let Some(existing) = self.get_intrinsic(intrinsic) {
return *existing;
}
self.values.insert(Value::Intrinsic(intrinsic))
let intrinsic_value_id = self.values.insert(Value::Intrinsic(intrinsic));
self.intrinsics.insert(intrinsic, intrinsic_value_id);
intrinsic_value_id
}

pub(crate) fn get_intrinsic(&mut self, intrinsic: Intrinsic) -> Option<&ValueId> {
self.intrinsics.get(&intrinsic)
}

/// Attaches results to the instruction, clearing any previous results.
Expand Down Expand Up @@ -322,7 +339,10 @@ impl DataFlowGraph {
) -> Option<(im::Vector<ValueId>, Rc<CompositeType>)> {
match &self.values[self.resolve(value)] {
// Vectors are shared, so cloning them is cheap
Value::Array { array, element_type } => Some((array.clone(), element_type.clone())),
Value::Array { array, element_type } | Value::Slice { array, element_type } => {
Some((array.clone(), element_type.clone()))
}
// Value::Array { array, element_type } => Some((array.clone(), element_type.clone())),
vezenovm marked this conversation as resolved.
Show resolved Hide resolved
_ => None,
}
}
Expand Down
42 changes: 38 additions & 4 deletions crates/noirc_evaluator/src/ssa_refactor/ir/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use super::{
basic_block::BasicBlockId,
dfg::DataFlowGraph,
map::Id,
types::Type,
types::{NumericType, Type},
value::{Value, ValueId},
};

Expand All @@ -30,6 +30,8 @@ pub(crate) type InstructionId = Id<Instruction>;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub(crate) enum Intrinsic {
Sort,
ArrayLen,
jfecher marked this conversation as resolved.
Show resolved Hide resolved
SlicePushBack,
Println,
ToBits(Endian),
ToRadix(Endian),
Expand All @@ -41,6 +43,8 @@ impl std::fmt::Display for Intrinsic {
match self {
Intrinsic::Println => write!(f, "println"),
Intrinsic::Sort => write!(f, "arraysort"),
Intrinsic::ArrayLen => write!(f, "array_len"),
Intrinsic::SlicePushBack => write!(f, "slice_push_back"),
Intrinsic::ToBits(Endian::Big) => write!(f, "to_be_bits"),
Intrinsic::ToBits(Endian::Little) => write!(f, "to_le_bits"),
Intrinsic::ToRadix(Endian::Big) => write!(f, "to_be_radix"),
Expand All @@ -57,6 +61,8 @@ impl Intrinsic {
match name {
"println" => Some(Intrinsic::Println),
"arraysort" => Some(Intrinsic::Sort),
"array_len" => Some(Intrinsic::ArrayLen),
"slice_push_back" => Some(Intrinsic::SlicePushBack),
"to_le_radix" => Some(Intrinsic::ToRadix(Endian::Little)),
"to_be_radix" => Some(Intrinsic::ToRadix(Endian::Big)),
"to_le_bits" => Some(Intrinsic::ToBits(Endian::Little)),
Expand Down Expand Up @@ -297,7 +303,6 @@ impl Instruction {
Instruction::ArrayGet { array, index } => {
let array = dfg.get_array_constant(*array);
let index = dfg.get_numeric_constant(*index);

if let (Some((array, _)), Some(index)) = (array, index) {
let index =
index.try_to_u64().expect("Expected array index to fit in u64") as usize;
Expand All @@ -310,7 +315,6 @@ impl Instruction {
Instruction::ArraySet { array, index, value } => {
let array = dfg.get_array_constant(*array);
let index = dfg.get_numeric_constant(*index);

if let (Some((array, element_type)), Some(index)) = (array, index) {
let index =
index.try_to_u64().expect("Expected array index to fit in u64") as usize;
Expand All @@ -329,7 +333,36 @@ impl Instruction {
None
}
}
Instruction::Call { .. } => None,
Instruction::Call { func, arguments } => {
let mut simplify_result = None;
if let Some(intrinsic) = Intrinsic::lookup("slice_push_back") {
if let Some(intrinsic) = dfg.get_intrinsic(intrinsic) {
if func == intrinsic {
jfecher marked this conversation as resolved.
Show resolved Hide resolved
let slice = dfg.get_array_constant(arguments[0]);
if let (Some((mut slice, element_type)), elem) = (slice, arguments[1]) {
slice.push_back(elem);
let new_slice = dfg.make_slice(slice, element_type);
simplify_result = SimplifiedTo(new_slice);
}
}
}
}
if let Some(intrinsic) = Intrinsic::lookup("array_len") {
if let Some(intrinsic) = dfg.get_intrinsic(intrinsic) {
if func == intrinsic {
let slice = dfg.get_array_constant(arguments[0]);
jfecher marked this conversation as resolved.
Show resolved Hide resolved
if let Some((slice, _)) = slice {
let slice_len = dfg.make_constant(
FieldElement::from(slice.len() as u128),
Type::Numeric(NumericType::NativeField),
);
simplify_result = SimplifiedTo(slice_len);
}
}
}
};
simplify_result
}
Instruction::Allocate { .. } => None,
Instruction::Load { .. } => None,
Instruction::Store { .. } => None,
Expand Down Expand Up @@ -696,6 +729,7 @@ impl std::fmt::Display for BinaryOp {

/// Contains the result to Instruction::simplify, specifying how the instruction
/// should be simplified.
#[derive(Debug, Clone)]
jfecher marked this conversation as resolved.
Show resolved Hide resolved
pub(crate) enum SimplifyResult {
/// Replace this function's result with the given value
SimplifiedTo(ValueId),
Expand Down
4 changes: 4 additions & 0 deletions crates/noirc_evaluator/src/ssa_refactor/ir/printer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ fn value(function: &Function, id: ValueId) -> String {
let elements = vecmap(array, |element| value(function, *element));
format!("[{}]", elements.join(", "))
}
Value::Slice { element_type, .. } => {
let elements = vecmap(element_type.as_slice(), ToString::to_string);
format!("{:?}", elements)
jfecher marked this conversation as resolved.
Show resolved Hide resolved
}
Value::Param { .. } | Value::Instruction { .. } => id.to_string(),
}
}
Expand Down
4 changes: 4 additions & 0 deletions crates/noirc_evaluator/src/ssa_refactor/ir/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ pub(crate) enum Value {
/// Represents a constant array value
Array { array: im::Vector<ValueId>, element_type: Rc<CompositeType> },

/// Represents a compile-time array
Slice { array: im::Vector<ValueId>, element_type: Rc<CompositeType> },
jfecher marked this conversation as resolved.
Show resolved Hide resolved

/// This Value refers to a function in the IR.
/// Functions always have the type Type::Function.
/// If the argument or return types are needed, users should retrieve
Expand All @@ -60,6 +63,7 @@ impl Value {
Value::Param { typ, .. } => typ.clone(),
Value::NumericConstant { typ, .. } => typ.clone(),
Value::Array { element_type, array } => Type::Array(element_type.clone(), array.len()),
Value::Slice { .. } => Type::Reference,
Value::Function { .. } => Type::Function,
Value::Intrinsic { .. } => Type::Function,
}
Expand Down
5 changes: 5 additions & 0 deletions crates/noirc_evaluator/src/ssa_refactor/opt/inlining.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,11 @@ impl<'function> PerFunctionContext<'function> {
let elements = array.iter().map(|value| self.translate_value(*value)).collect();
self.context.builder.array_constant(elements, element_type.clone())
}
Value::Slice { array: initial_array, element_type } => {
jfecher marked this conversation as resolved.
Show resolved Hide resolved
let elements =
initial_array.iter().map(|value| self.translate_value(*value)).collect();
self.context.builder.slice(elements, element_type.clone())
}
};

self.values.insert(id, new_value);
Expand Down
8 changes: 8 additions & 0 deletions crates/noirc_evaluator/src/ssa_refactor/ssa_builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,14 @@ impl FunctionBuilder {
self.current_function.dfg.make_array(elements, element_types)
}

pub(crate) fn slice(
&mut self,
elements: im::Vector<ValueId>,
element_types: Rc<CompositeType>,
) -> ValueId {
self.current_function.dfg.make_slice(elements, element_types)
}

/// Returns the type of the given value.
pub(crate) fn type_of_value(&self, value: ValueId) -> Type {
self.current_function.dfg.type_of_value(value)
Expand Down
1 change: 1 addition & 0 deletions crates/noirc_evaluator/src/ssa_refactor/ssa_gen/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ impl<'a> FunctionContext<'a> {
ast::Type::Unit => panic!("convert_non_tuple_type called on a unit type"),
ast::Type::Tuple(_) => panic!("convert_non_tuple_type called on a tuple: {typ}"),
ast::Type::Function(_, _) => Type::Function,
ast::Type::Slice(_) => Type::Reference,

// How should we represent Vecs?
// Are they a struct of array + length + capacity?
Expand Down
4 changes: 3 additions & 1 deletion crates/noirc_frontend/src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ use iter_extended::vecmap;
pub enum UnresolvedType {
FieldElement(CompTime),
Array(Option<UnresolvedTypeExpression>, Box<UnresolvedType>), // [4]Witness = Array(4, Witness)
Integer(CompTime, Signedness, u32), // u32 = Integer(unsigned, 32)
Slice(Box<UnresolvedType>),
Integer(CompTime, Signedness, u32), // u32 = Integer(unsigned, 32)
Bool(CompTime),
Expression(UnresolvedTypeExpression),
String(Option<UnresolvedTypeExpression>),
Expand Down Expand Up @@ -86,6 +87,7 @@ impl std::fmt::Display for UnresolvedType {
None => write!(f, "[{typ}]"),
Some(len) => write!(f, "[{typ}; {len}]"),
},
Slice(typ) => write!(f, "[{typ}]"),
Integer(is_const, sign, num_bits) => match sign {
Signedness::Signed => write!(f, "{is_const}i{num_bits}"),
Signedness::Unsigned => write!(f, "{is_const}u{num_bits}"),
Expand Down
7 changes: 7 additions & 0 deletions crates/noirc_frontend/src/hir/resolution/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,9 @@ impl<'a> Resolver<'a> {
let elem = Box::new(self.resolve_type_inner(*elem, new_variables));
Type::Array(Box::new(resolved_size), elem)
}
UnresolvedType::Slice(elem) => {
Type::Slice(Box::new(self.resolve_type_inner(*elem, new_variables)))
}
UnresolvedType::Expression(expr) => self.convert_expression_type(expr),
UnresolvedType::Integer(comp_time, sign, bits) => Type::Integer(comp_time, sign, bits),
UnresolvedType::Bool(comp_time) => Type::Bool(comp_time),
Expand Down Expand Up @@ -759,6 +762,10 @@ impl<'a> Resolver<'a> {
}
}

Type::Slice(typ) => {
Self::find_numeric_generics_in_type(typ, found);
}

Type::Tuple(fields) => {
for field in fields {
Self::find_numeric_generics_in_type(field, found);
Expand Down
1 change: 1 addition & 0 deletions crates/noirc_frontend/src/hir/type_check/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ impl<'interner> TypeChecker<'interner> {
// XXX: We can check the array bounds here also, but it may be better to constant fold first
// and have ConstId instead of ExprId for constants
Type::Array(_, base_type) => *base_type,
Type::Slice(base_type) => *base_type,
Type::Error => Type::Error,
typ => {
let span = self.interner.expr_span(&index_expr.collection);
Expand Down
1 change: 1 addition & 0 deletions crates/noirc_frontend/src/hir/type_check/stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ impl<'interner> TypeChecker<'interner> {

let typ = match result {
Type::Array(_, elem_type) => *elem_type,
Type::Slice(elem_type) => *elem_type,
Type::Error => Type::Error,
other => {
// TODO: Need a better span here
Expand Down
Loading