Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 7 additions & 0 deletions debug_utils/sierra-emu/src/vm/const.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,13 @@ fn inner(

Value::Struct(fields)
}
CoreTypeConcrete::EcPoint(_) => match inner_data {
[GenericArg::Value(x), GenericArg::Value(y)] => Value::EcPoint {
x: x.into(),
y: y.into(),
},
_ => unreachable!(),
},
CoreTypeConcrete::Enum(_) => match inner_data {
[GenericArg::Value(value_idx), GenericArg::Type(payload_ty)] => {
let payload_type = registry.get_type(payload_ty).unwrap();
Expand Down
69 changes: 37 additions & 32 deletions src/libfuncs/const.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{
metadata::{realloc_bindings::ReallocBindingsMeta, MetadataStorage},
native_panic,
types::TypeBuilder,
utils::{ProgramRegistryExt, RangeExt, PRIME},
utils::{felt_to_unsigned, ProgramRegistryExt, RangeExt},
};
use cairo_lang_sierra::{
extensions::{
Expand All @@ -25,10 +25,9 @@ use cairo_lang_sierra::{
use melior::{
dialect::llvm::{self, r#type::pointer},
helpers::{ArithBlockExt, BuiltinBlockExt, LlvmBlockExt},
ir::{Block, Location, Value},
ir::{r#type::IntegerType, Block, Location, Value},
Context,
};
use num_bigint::Sign;

/// Select and call the correct libfunc builder function from the selector.
pub fn build<'ctx, 'this>(
Expand Down Expand Up @@ -254,36 +253,33 @@ pub fn build_const_type_value<'ctx, 'this>(
inner_type.integer_range(registry)?.offset_bit_width(),
)?)
}
CoreTypeConcrete::Felt252(_) => {
let value = match &info.inner_data.as_slice() {
[GenericArg::Value(value)] => value.clone(),
_ => return Err(Error::ConstDataMismatch),
};

let (sign, value) = value.into_parts();
let value = match sign {
Sign::Minus => PRIME.clone() - value,
_ => value,
};

Ok(entry.const_int_from_type(context, location, value, inner_ty)?)
}
CoreTypeConcrete::Starknet(
CoreTypeConcrete::Felt252(_)
| CoreTypeConcrete::Starknet(
StarknetTypeConcrete::ClassHash(_) | StarknetTypeConcrete::ContractAddress(_),
) => {
let value = match &info.inner_data.as_slice() {
[GenericArg::Value(value)] => value.clone(),
_ => return Err(Error::ConstDataMismatch),
};

let (sign, value) = value.into_parts();
let value = match sign {
Sign::Minus => PRIME.clone() - value,
_ => value,
};

Ok(entry.const_int_from_type(context, location, value, inner_ty)?)
}
) => match &info.inner_data[..] {
[GenericArg::Value(value)] => Ok(entry.const_int_from_type(
context,
location,
felt_to_unsigned(value),
inner_ty,
)?),
_ => Err(Error::ConstDataMismatch),
},
CoreTypeConcrete::EcPoint(_) => match &info.inner_data[..] {
[GenericArg::Value(x), GenericArg::Value(y)] => {
let felt252_ty = IntegerType::new(context, 252).into();

let x = entry.const_int(context, location, felt_to_unsigned(x), 252)?;
let y = entry.const_int(context, location, felt_to_unsigned(y), 252)?;

let ec_point_ty = llvm::r#type::r#struct(context, &[felt252_ty, felt252_ty], false);
let value = entry.append_op_result(llvm::undef(ec_point_ty, location))?;
let value = entry.insert_value(context, location, value, x, 0)?;
let value = entry.insert_value(context, location, value, y, 1)?;
Ok(value)
}
_ => Err(Error::ConstDataMismatch),
},
CoreTypeConcrete::Uint8(_)
| CoreTypeConcrete::Uint16(_)
| CoreTypeConcrete::Uint32(_)
Expand Down Expand Up @@ -319,4 +315,13 @@ pub mod test {
let result = run_program(&program, "run_test", &[]).return_value;
assert_eq!(result, jit_struct!(Value::Sint32(-2)));
}

#[test]
fn run_ec_point_const() {
// Tests const_as_box on EcPoint type (Const<EcPoint, x, y>).
let program = get_compiled_program("test_data_artifacts/programs/libfuncs/ec_point_const");

// Just verify it compiles and runs without panicking.
let _ = run_program(&program, "run_test", &[]);
}
}
27 changes: 9 additions & 18 deletions src/libfuncs/felt252.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use super::LibfuncHelper;
use crate::{
error::{panic::ToNativeAssertError, Result},
metadata::{runtime_bindings::RuntimeBindingsMeta, MetadataStorage},
utils::{ProgramRegistryExt, PRIME},
utils::{felt_to_unsigned, ProgramRegistryExt, PRIME},
};
use cairo_lang_sierra::{
extensions::{
Expand All @@ -24,7 +24,6 @@ use melior::{
ir::{r#type::IntegerType, Block, Location, Value, ValueLike},
Context,
};
use num_bigint::{BigInt, Sign};

/// Select and call the correct libfunc builder function from the selector.
pub fn build<'ctx, 'this>(
Expand Down Expand Up @@ -77,15 +76,13 @@ pub fn build_binary_operation<'ctx, 'this>(
(operation.operator, entry.arg(0)?, entry.arg(1)?)
}
Felt252BinaryOperationConcrete::WithConst(operation) => {
let value = match operation.c.sign() {
Sign::Minus => (BigInt::from_biguint(Sign::Plus, PRIME.clone()) + &operation.c)
.magnitude()
.clone(),
_ => operation.c.magnitude().clone(),
};

// TODO: Ensure that the constant is on the correct side of the operation.
let rhs = entry.const_int_from_type(context, location, value, felt252_ty)?;
let rhs = entry.const_int_from_type(
context,
location,
felt_to_unsigned(&operation.c),
felt252_ty,
)?;

(operation.operator, entry.arg(0)?, rhs)
}
Expand Down Expand Up @@ -206,21 +203,15 @@ pub fn build_const<'ctx, 'this>(
metadata: &mut MetadataStorage,
info: &Felt252ConstConcreteLibfunc,
) -> Result<()> {
let value = match info.c.sign() {
Sign::Minus => (&info.c + BigInt::from_biguint(Sign::Plus, PRIME.clone()))
.magnitude()
.clone(),
_ => info.c.magnitude().clone(),
};

let felt252_ty = registry.build_type(
context,
helper,
metadata,
&info.branch_signatures()[0].vars[0].ty,
)?;

let value = entry.const_int_from_type(context, location, value, felt252_ty)?;
let value =
entry.const_int_from_type(context, location, felt_to_unsigned(&info.c), felt252_ty)?;

helper.br(entry, 0, &[value], location)
}
Expand Down
33 changes: 4 additions & 29 deletions src/libfuncs/starknet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
ffi::get_struct_field_type_at,
metadata::{drop_overrides::DropOverridesMeta, MetadataStorage},
starknet::handler::StarknetSyscallHandlerCallbacks,
utils::{get_integer_layout, ProgramRegistryExt, PRIME},
utils::{felt_to_unsigned, get_integer_layout, ProgramRegistryExt},
};
use cairo_lang_sierra::{
extensions::{
Expand All @@ -31,7 +31,6 @@ use melior::{
},
Context,
};
use num_bigint::Sign;
use std::alloc::Layout;

mod secp256;
Expand Down Expand Up @@ -306,15 +305,7 @@ pub fn build_class_hash_const<'ctx, 'this>(
_metadata: &mut MetadataStorage,
info: &SignatureAndConstConcreteLibfunc,
) -> Result<()> {
let value = entry.const_int(
context,
location,
match info.c.sign() {
Sign::Minus => &*PRIME - info.c.magnitude(),
_ => info.c.magnitude().clone(),
},
252,
)?;
let value = entry.const_int(context, location, felt_to_unsigned(&info.c), 252)?;

helper.br(entry, 0, &[value], location)
}
Expand Down Expand Up @@ -365,15 +356,7 @@ pub fn build_contract_address_const<'ctx, 'this>(
_metadata: &mut MetadataStorage,
info: &SignatureAndConstConcreteLibfunc,
) -> Result<()> {
let value = entry.const_int(
context,
location,
match info.c.sign() {
Sign::Minus => &*PRIME - info.c.magnitude(),
_ => info.c.magnitude().clone(),
},
252,
)?;
let value = entry.const_int(context, location, felt_to_unsigned(&info.c), 252)?;

helper.br(entry, 0, &[value], location)
}
Expand Down Expand Up @@ -596,15 +579,7 @@ pub fn build_storage_base_address_const<'ctx, 'this>(
_metadata: &mut MetadataStorage,
info: &SignatureAndConstConcreteLibfunc,
) -> Result<()> {
let value = entry.const_int(
context,
location,
match info.c.sign() {
Sign::Minus => &*PRIME - info.c.magnitude(),
_ => info.c.magnitude().clone(),
},
252,
)?;
let value = entry.const_int(context, location, felt_to_unsigned(&info.c), 252)?;

helper.br(entry, 0, &[value], location)
}
Expand Down
10 changes: 10 additions & 0 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,16 @@ pub fn find_function_id<'a>(program: &'a Program, function_name: &str) -> Option
.map(|func| &func.id)
}

/// Normalize a signed BigInt felt value to its unsigned field representation.
///
/// Negative values are mapped to `PRIME - |value|`.
pub fn felt_to_unsigned(value: &BigInt) -> BigUint {
match value.sign() {
Sign::Minus => &*PRIME - value.magnitude(),
_ => value.magnitude().clone(),
}
}

/// Parse a numeric string into felt, wrapping negatives around the prime modulo.
pub fn felt252_str(value: &str) -> Felt {
let value = value
Expand Down
17 changes: 17 additions & 0 deletions test_data/programs/libfuncs/ec_point_const.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use core::ec::EcPoint;

mod value {
extern type Const<T, const X: felt252, const Y: felt252>;
}
extern fn const_as_box<T, const SEGMENT_INDEX: felt252>() -> Box<EcPoint> nopanic;

fn run_test() -> Box<EcPoint> {
const_as_box::<
value::Const<
EcPoint,
0x1ef15c18599971b7beced415a40f0c7deacfd9b0d1819e03d723d8bc943cfca,
0x5668060aa49730b7be4801df46ec62de53ecd11abe43a32873000c36e8dc1f,
>,
0,
>()
}
Loading