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

chore(ssa): indent NumericType into ObjectType #810

Merged
merged 8 commits into from
Mar 31, 2023
6 changes: 3 additions & 3 deletions crates/noirc_evaluator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use errors::{RuntimeError, RuntimeErrorKind};
use iter_extended::btree_map;
use noirc_abi::{AbiType, AbiVisibility};
use noirc_frontend::monomorphization::ast::*;
use ssa::{code_gen::IRGenerator, node};
use ssa::{code_gen::IRGenerator, node::ObjectType};
use std::collections::BTreeMap;

pub struct Evaluator {
Expand Down Expand Up @@ -151,7 +151,7 @@ impl Evaluator {
ir_gen.create_new_variable(
name.to_owned(),
Some(def),
node::ObjectType::NativeField,
ObjectType::native_field(),
Some(witness),
);
}
Expand All @@ -177,7 +177,7 @@ impl Evaluator {
if *visibility == AbiVisibility::Public {
self.public_inputs.push(witness);
}
let obj_type = node::ObjectType::Boolean;
let obj_type = ObjectType::Boolean;
ir_gen.create_new_variable(name.to_owned(), Some(def), obj_type, Some(witness));
}
AbiType::Struct { fields } => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,7 @@ impl InternalVarCache {
NodeObject::Obj(variable) => {
let variable_type = variable.get_type();
match variable_type {
ObjectType::Boolean
| ObjectType::NativeField
| ObjectType::Signed(..)
| ObjectType::Unsigned(..) => {
ObjectType::Boolean | ObjectType::Numeric(..) => {
let witness =
variable.witness.unwrap_or_else(|| evaluator.add_witness_to_cs());
InternalVar::from_witness(witness)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ pub(crate) fn evaluate(
BinaryOp::Sub { max_rhs_value } | BinaryOp::SafeSub { max_rhs_value } => {
let l_c = var_cache.get_or_compute_internal_var_unwrap(binary.lhs, evaluator, ctx);
let r_c = var_cache.get_or_compute_internal_var_unwrap(binary.rhs, evaluator, ctx);
if res_type == ObjectType::NativeField {
if res_type.is_native_field() {
InternalVar::from(constraints::subtract(
l_c.expression(),
FieldElement::one(),
Expand Down
2 changes: 1 addition & 1 deletion crates/noirc_evaluator/src/ssa/anchor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub enum CseAction {
#[derive(Default, Clone)]
pub struct Anchor {
map: HashMap<Opcode, HashMap<Operation, NodeId>>, //standard anchor
cast_map: HashMap<NodeId, HashMap<crate::node::ObjectType, NodeId>>, //cast anchor
cast_map: HashMap<NodeId, HashMap<ObjectType, NodeId>>, //cast anchor
mem_map: HashMap<ArrayId, Vec<VecDeque<(usize, NodeId)>>>, //Memory anchor: one Vec for each array where Vec[i] contains the list of load and store instructions having index i, and the mem_item position in which they appear
mem_list: HashMap<ArrayId, VecDeque<MemItem>>, // list of the memory instructions, per array, and grouped into MemItems
}
Expand Down
16 changes: 9 additions & 7 deletions crates/noirc_evaluator/src/ssa/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ impl Opcode {
BlackBoxFunc::SchnorrVerify
| BlackBoxFunc::EcdsaSecp256k1
| BlackBoxFunc::MerkleMembership => BigUint::one(),
BlackBoxFunc::HashToField128Security => ObjectType::NativeField.max_size(),
BlackBoxFunc::HashToField128Security => ObjectType::native_field().max_size(),
BlackBoxFunc::AES => {
todo!("ICE: AES is unimplemented")
}
Expand All @@ -75,21 +75,23 @@ impl Opcode {
Opcode::LowLevel(op) => {
match op {
BlackBoxFunc::AES => todo!("ICE: AES is unimplemented"),
BlackBoxFunc::SHA256 | BlackBoxFunc::Blake2s => (32, ObjectType::Unsigned(8)),
BlackBoxFunc::HashToField128Security => (1, ObjectType::NativeField),
BlackBoxFunc::SHA256 | BlackBoxFunc::Blake2s => {
(32, ObjectType::unsigned_integer(8))
}
BlackBoxFunc::HashToField128Security => (1, ObjectType::native_field()),
// See issue #775 on changing this to return a boolean
BlackBoxFunc::MerkleMembership
| BlackBoxFunc::SchnorrVerify
| BlackBoxFunc::EcdsaSecp256k1 => (1, ObjectType::NativeField),
BlackBoxFunc::Pedersen => (2, ObjectType::NativeField),
BlackBoxFunc::FixedBaseScalarMul => (2, ObjectType::NativeField),
| BlackBoxFunc::EcdsaSecp256k1 => (1, ObjectType::native_field()),
BlackBoxFunc::Pedersen => (2, ObjectType::native_field()),
BlackBoxFunc::FixedBaseScalarMul => (2, ObjectType::native_field()),
BlackBoxFunc::RANGE | BlackBoxFunc::AND | BlackBoxFunc::XOR => {
unreachable!("ICE: these opcodes do not have Noir builtin functions")
}
}
}
Opcode::ToBits => (FieldElement::max_num_bits(), ObjectType::Boolean),
Opcode::ToRadix => (FieldElement::max_num_bits(), ObjectType::NativeField),
Opcode::ToRadix => (FieldElement::max_num_bits(), ObjectType::native_field()),
}
}
}
11 changes: 6 additions & 5 deletions crates/noirc_evaluator/src/ssa/code_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,10 +153,10 @@ impl IRGenerator {

pub fn get_object_type_from_abi(&self, el_type: &noirc_abi::AbiType) -> ObjectType {
match el_type {
noirc_abi::AbiType::Field => ObjectType::NativeField,
noirc_abi::AbiType::Field => ObjectType::native_field(),
noirc_abi::AbiType::Integer { sign, width, .. } => match sign {
noirc_abi::Sign::Unsigned => ObjectType::Unsigned(*width),
noirc_abi::Sign::Signed => ObjectType::Signed(*width),
noirc_abi::Sign::Unsigned => ObjectType::unsigned_integer(*width),
noirc_abi::Sign::Signed => ObjectType::signed_integer(*width),
},
noirc_abi::AbiType::Boolean => ObjectType::Boolean,
noirc_abi::AbiType::Array { .. } => {
Expand Down Expand Up @@ -383,7 +383,8 @@ impl IRGenerator {
Value::Single(v_id)
}
Type::String(len) => {
let obj_type = ObjectType::Unsigned(8);
// TODO: document why this is 8
kevaundray marked this conversation as resolved.
Show resolved Hide resolved
let obj_type = ObjectType::unsigned_integer(8);
let len = *len;
let (v_id, _) = self.new_array(base_name, obj_type, len.try_into().unwrap(), def);
Value::Single(v_id)
Expand Down Expand Up @@ -571,7 +572,7 @@ impl IRGenerator {
for (pos, object) in elements.into_iter().enumerate() {
let lhs_adr = self.context.get_or_create_const(
FieldElement::from((pos as u32) as u128),
ObjectType::NativeField,
ObjectType::native_field(),
);
let store = Operation::Store { array_id, index: lhs_adr, value: object };
self.context.new_instruction(store, element_type)?;
Expand Down
4 changes: 2 additions & 2 deletions crates/noirc_evaluator/src/ssa/conditional.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::ssa::{
context::SsaContext,
flatten::UnrollContext,
inline::StackFrame,
node::{BinaryOp, Instruction, Mark, NodeId, ObjectType, Opcode, Operation},
node::{Binary, BinaryOp, Instruction, Mark, NodeId, ObjectType, Opcode, Operation},
{block, flatten, node, optimizations},
};
use crate::{errors, errors::RuntimeError};
Expand Down Expand Up @@ -605,7 +605,7 @@ impl DecisionTree {
}
if ctx.under_assumption(cond) {
let ins2 = ctx.get_mut_instruction(ins_id);
ins2.operation = Operation::Binary(crate::node::Binary {
ins2.operation = Operation::Binary(Binary {
lhs: binary_op.lhs,
rhs: binary_op.rhs,
operator: binary_op.operator.clone(),
Expand Down
39 changes: 25 additions & 14 deletions crates/noirc_evaluator/src/ssa/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -792,10 +792,14 @@ impl SsaContext {
let len = self.mem[a].len;
let e_type = self.mem[b].element_type;
for i in 0..len {
let idx_b = self
.get_or_create_const(FieldElement::from(i as i128), ObjectType::Unsigned(32));
let idx_a = self
.get_or_create_const(FieldElement::from(i as i128), ObjectType::Unsigned(32));
let idx_b = self.get_or_create_const(
FieldElement::from(i as i128),
ObjectType::unsigned_integer(32),
);
let idx_a = self.get_or_create_const(
FieldElement::from(i as i128),
ObjectType::unsigned_integer(32),
);
let op_b = Operation::Load { array_id: b, index: idx_b };
let load = self.new_instruction(op_b, e_type)?;
let op_a = Operation::Store { array_id: a, index: idx_a, value: load };
Expand Down Expand Up @@ -937,8 +941,10 @@ impl SsaContext {
let len = self.mem[array_id].len;
let e_type = self.mem[array_id].element_type;
for i in 0..len {
let index =
self.get_or_create_const(FieldElement::from(i as i128), ObjectType::Unsigned(32));
let index = self.get_or_create_const(
FieldElement::from(i as i128),
ObjectType::unsigned_integer(32),
);
let op_a = Operation::Store { array_id, index, value: self.zero_with_type(e_type) };
self.new_instruction_inline(op_a, e_type, stack_frame);
}
Expand All @@ -958,10 +964,15 @@ impl SsaContext {
let len = self.mem[a].len;
let e_type = self.mem[b].element_type;
for i in 0..len {
let idx_b = self
.get_or_create_const(FieldElement::from(i as i128), ObjectType::Unsigned(32));
let idx_a = self
.get_or_create_const(FieldElement::from(i as i128), ObjectType::Unsigned(32));
let idx_b = self.get_or_create_const(
FieldElement::from(i as i128),
// TODO: Should document where 32 comes from
ObjectType::unsigned_integer(32),
);
let idx_a = self.get_or_create_const(
FieldElement::from(i as i128),
ObjectType::unsigned_integer(32),
);
let op_b = Operation::Load { array_id: b, index: idx_b };
let load = self.new_instruction_inline(op_b, e_type, stack_frame);
let op_a = Operation::Store { array_id: a, index: idx_a, value: load };
Expand Down Expand Up @@ -1050,7 +1061,7 @@ impl SsaContext {
let (id, array_id) = self.new_array(&name, el_type, len, None);
for i in 0..len {
let index = self
.get_or_create_const(FieldElement::from(i as u128), ObjectType::NativeField);
.get_or_create_const(FieldElement::from(i as u128), ObjectType::native_field());
self.current_block = block1;
let op = Operation::Load { array_id: adr1, index };
let v1 = self.new_instruction(op, el_type).unwrap();
Expand Down Expand Up @@ -1120,15 +1131,15 @@ impl SsaContext {
use noirc_frontend::Signedness;
match t {
Type::Bool => ObjectType::Boolean,
Type::Field => ObjectType::NativeField,
Type::Field => ObjectType::native_field(),
Type::Integer(sign, bit_size) => {
assert!(
*bit_size < super::integer::short_integer_max_bit_size(),
"long integers are not yet supported"
);
match sign {
Signedness::Signed => ObjectType::Signed(*bit_size),
Signedness::Unsigned => ObjectType::Unsigned(*bit_size),
Signedness::Signed => ObjectType::signed_integer(*bit_size),
Signedness::Unsigned => ObjectType::unsigned_integer(*bit_size),
}
}
Type::Array(..) => panic!("Cannot convert an array type {t} into an ObjectType since it is unknown which array it refers to"),
Expand Down
12 changes: 6 additions & 6 deletions crates/noirc_evaluator/src/ssa/integer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ fn get_instruction_max_operand(
Operation::Binary(node::Binary { operator, lhs, rhs, .. }) => {
if let BinaryOp::Sub { .. } = operator {
//TODO uses interval analysis instead
if matches!(ins.res_type, ObjectType::Unsigned(_)) {
if ins.res_type.is_unsigned_integer() {
if let Some(lhs_const) = ctx.get_as_constant(*lhs) {
let lhs_big = BigUint::from_bytes_be(&lhs_const.to_be_bytes());
if max_map[rhs] <= lhs_big {
Expand Down Expand Up @@ -266,14 +266,14 @@ fn block_overflow(
let ins_max_bits = get_instruction_max(ctx, &ins, max_map, &value_map).bits();
let res_type = ins.res_type;

let too_many_bits = ins_max_bits > FieldElement::max_num_bits() as u64
&& res_type != ObjectType::NativeField;
let too_many_bits =
ins_max_bits > FieldElement::max_num_bits() as u64 && !res_type.is_native_field();

ins.operation.for_each_id(|id| {
get_obj_max_value(ctx, id, max_map, &value_map);
let arg = ctx.try_get_node(id);
let should_truncate_arg =
should_truncate_ins && arg.is_some() && get_type(arg) != ObjectType::NativeField;
should_truncate_ins && arg.is_some() && !get_type(arg).is_native_field();

if should_truncate_arg || too_many_bits {
add_to_truncate(ctx, id, get_size_in_bits(arg), &mut truncate_map, max_map);
Expand Down Expand Up @@ -308,7 +308,7 @@ fn block_overflow(
}
}
Operation::Binary(node::Binary { operator: BinaryOp::Shr, lhs, rhs, .. }) => {
if !matches!(ins.res_type, node::ObjectType::Unsigned(_)) {
if !ins.res_type.is_unsigned_integer() {
todo!("Right shift is only implemented for unsigned integers");
}
if let Some(r_const) = ctx.get_as_constant(rhs) {
Expand Down Expand Up @@ -490,7 +490,7 @@ fn get_max_value(ins: &Instruction, max_map: &mut HashMap<NodeId, BigUint>) -> B
Operation::Intrinsic(opcode, _) => opcode.get_max_value(),
};

if ins.res_type == ObjectType::NativeField {
if ins.res_type.is_native_field() {
let field_max = BigUint::from_bytes_be(&FieldElement::one().neg().to_be_bytes());

//Native Field operations cannot overflow so they will not be truncated
Expand Down
Loading