Skip to content

Commit

Permalink
Merge pull request #58 from FractalFir/methodref
Browse files Browse the repository at this point in the history
Added i128 multiplaction overflow checks
  • Loading branch information
FractalFir authored Oct 7, 2024
2 parents 9c6545d + 2feab4f commit addeecb
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 9 deletions.
4 changes: 3 additions & 1 deletion cilly/src/bin/linker/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,7 @@ fn main() {
cilly::v2::builtins::casts::insert_casts(&mut final_assembly, &mut overrides);
cilly::v2::builtins::insert_heap(&mut final_assembly, &mut overrides);
cilly::v2::builtins::generate_int128_ops(&mut final_assembly, &mut overrides, *C_MODE);
cilly::v2::builtins::i128_mul_ovf_check(&mut final_assembly, &mut overrides);
if !*C_MODE {
cilly::v2::builtins::atomics::generate_all_atomics(&mut final_assembly, &mut overrides);
cilly::v2::builtins::instert_threading(&mut final_assembly, &mut overrides);
Expand All @@ -389,7 +390,8 @@ fn main() {
NonZeroU32::new(16),
));

final_assembly.patch_missing_methods(externs, modifies_errno, overrides);
final_assembly.patch_missing_methods(&externs, &modifies_errno, &overrides);
final_assembly.patch_missing_methods(&externs, &modifies_errno, &overrides);

add_mandatory_statics(&mut final_assembly);
if *DEAD_CODE_ELIMINATION {
Expand Down
15 changes: 10 additions & 5 deletions cilly/src/v2/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -842,18 +842,23 @@ impl Assembly {

pub fn patch_missing_methods(
&mut self,
externs: FxHashMap<&str, String>,
modifies_errno: FxHashSet<&str>,
override_methods: MissingMethodPatcher,
externs: &FxHashMap<&str, String>,
modifies_errno: &FxHashSet<&str>,
override_methods: &MissingMethodPatcher,
) {
let mref_count = self.method_refs.0.len();
let externs: FxHashMap<_, _> = externs
.into_iter()
.map(|(fn_name, lib_name)| (self.alloc_string(fn_name), self.alloc_string(lib_name)))
.map(|(fn_name, lib_name)| {
(
self.alloc_string(fn_name.clone()),
self.alloc_string(lib_name.clone()),
)
})
.collect();
let preserve_errno: FxHashSet<_> = modifies_errno
.into_iter()
.map(|fn_name| self.alloc_string(fn_name))
.map(|fn_name| self.alloc_string(fn_name.clone()))
.collect();
for index in 0..mref_count {
// Get the full method refernce
Expand Down
74 changes: 73 additions & 1 deletion cilly/src/v2/builtins/int128/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::{
v2::{
asm::MissingMethodPatcher, Assembly, BasicBlock, BinOp, CILNode, CILRoot, Int, MethodImpl,
},
Type,
BranchCond, ClassRef, Const, Type,
};

pub fn op_direct(
Expand Down Expand Up @@ -99,3 +99,75 @@ pub fn generate_int128_ops(asm: &mut Assembly, patcher: &mut MissingMethodPatche
}
}
}
pub fn i128_mul_ovf_check(asm: &mut Assembly, patcher: &mut MissingMethodPatcher) {
let name = asm.alloc_string("i128_mul_ovf_check");
let generator = move |_, asm: &mut Assembly| {
let lhs = asm.alloc_node(CILNode::LdArg(0));
let rhs = asm.alloc_node(CILNode::LdArg(1));
let i128_class = ClassRef::int_128(asm);
let get_zero = asm.alloc_string("get_Zero");
let op_equality = asm.alloc_string("eq_i128");
let op_mul = asm.alloc_string("mul_i128");
let op_div = asm.alloc_string("div_i128");
let i128_classref = asm[i128_class].clone();
let main_module = *asm.main_module();
let main_module = asm[main_module].clone();
let const_zero = i128_classref.static_mref(&[], Type::Int(Int::I128), get_zero, asm);
let const_zero = asm.alloc_node(CILNode::Call(Box::new((const_zero, [].into()))));
let i128_eq = main_module.static_mref(
&[Type::Int(Int::I128), Type::Int(Int::I128)],
Type::Bool,
op_equality,
asm,
);
let i128_mul = main_module.static_mref(
&[Type::Int(Int::I128), Type::Int(Int::I128)],
Type::Int(Int::I128),
op_mul,
asm,
);
let i128_div = main_module.static_mref(
&[Type::Int(Int::I128), Type::Int(Int::I128)],
Type::Int(Int::I128),
op_div,
asm,
);
let rhs_zero = asm.alloc_node(CILNode::Call(Box::new((i128_eq, [rhs, const_zero].into()))));
let jmp_nz = asm.alloc_root(CILRoot::Branch(Box::new((
0,
1,
Some(BranchCond::False(rhs_zero)),
))));
let ret_false = asm.alloc_node(Const::Bool(false));
let ret_false = asm.alloc_root(CILRoot::Ret(ret_false));
let lhs_mul_rhs = asm.alloc_node(CILNode::Call(Box::new((i128_mul, [lhs, rhs].into()))));
let recomputed_rhs = asm.alloc_node(CILNode::Call(Box::new((
i128_div,
[lhs_mul_rhs, rhs].into(),
))));
let ovf = asm.alloc_node(CILNode::Call(Box::new((
i128_eq,
[recomputed_rhs, rhs].into(),
))));
let ret_ovf = asm.alloc_root(CILRoot::Ret(ovf));

MethodImpl::MethodBody {
blocks: vec![
BasicBlock::new(vec![jmp_nz, ret_false], 0, None),
BasicBlock::new(vec![ret_ovf], 1, None),
],
locals: vec![],
}
};
patcher.insert(name, Box::new(generator));
}
#[test]
fn test() {
let op = BinOp::Eq;
let lhs_type = Int::I128;
panic!(
"{op}_{lhs_type}",
op = op.name(),
lhs_type = lhs_type.name()
);
}
18 changes: 16 additions & 2 deletions src/binop/checked/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use cilly::{
and, call,
cil_node::CILNode,
cil_root::CILRoot,
conv_i16, conv_i32, conv_i64, conv_i8, conv_isize, conv_u64, conv_usize, gt, gt_un, ldc_i32,
ldc_i64, ldc_u32, ldc_u64, lt, mul, or,
conv_i16, conv_i32, conv_i64, conv_i8, conv_isize, conv_u64, conv_usize, eq, gt, gt_un,
ldc_i32, ldc_i64, ldc_u32, ldc_u64, lt, mul, or,
v2::{cilnode::MethodKind, Assembly, ClassRef, FieldDesc, Int, MethodRef},
Type,
};
Expand Down Expand Up @@ -426,6 +426,20 @@ pub fn mul<'tcx>(
);
or!(gt, lt)
}
TyKind::Int(IntTy::I128) => {
let op_mul = MethodRef::new(
*ctx.main_module(),
ctx.alloc_string("i128_mul_ovf_check"),
ctx.sig([Type::Int(Int::I128), Type::Int(Int::I128)], Type::Bool),
MethodKind::Static,
vec![].into(),
);
eq!(
call!(ctx.alloc_methodref(op_mul), [ops_a.clone(), ops_b.clone()]),
CILNode::LdFalse
)
}

_ => {
eprintln!("WARINING: can't checked mul type {ty:?}");
CILNode::LdFalse
Expand Down
32 changes: 32 additions & 0 deletions test/arthm/num_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ pub fn test_variadic_fnptr() {
test!(!(p < q));
}
fn main() {
isqrt_test();
unsafe { black_box(ldexpf(black_box(434.43), 1232.3434)) };
check_float_nan();
const A: u32 = 0b0101100;
Expand Down Expand Up @@ -387,3 +388,34 @@ pub fn checked_next_multiple_of(lhs: i8, rhs: i8) -> Option<i8> {
pub fn add_signed(a: i8, b: i8) -> bool {
a.checked_add(b).is_none()
}
struct I128W(i64, i64);
fn isqrt_test() {
let val = i128::MAX;
let bytes = val.to_le_bytes();
for i in bytes {
unsafe { printf(c"i:%u\n".as_ptr(), i as u32) };
}
test_eq!(bytes[15], 127);
for n in i128::MAX - 127..=i128::MAX {
/* .chain()
.chain((0..i128::MAX.count_ones()).map(|exponent| (1 << exponent) - 1))
.chain((0..i128::MAX.count_ones()).map(|exponent| 1 << exponent)) */
let isqrt_n = n.isqrt();
unsafe {
printf(
c"n:%lld isqrt_n:%lld\n".as_ptr(),
core::mem::transmute::<i128, I128W>(n),
core::mem::transmute::<i128, I128W>(isqrt_n),
)
};
test!(isqrt_n
.checked_mul(isqrt_n)
.map(|isqrt_n_squared| isqrt_n_squared <= n)
.unwrap_or(false));

test!((isqrt_n + 1)
.checked_mul(isqrt_n + 1)
.map(|isqrt_n_plus_1_squared| n < isqrt_n_plus_1_squared)
.unwrap_or(true));
}
}

0 comments on commit addeecb

Please sign in to comment.