Skip to content

Commit

Permalink
Fixes to misc intrinsics
Browse files Browse the repository at this point in the history
  • Loading branch information
FractalFir committed Aug 8, 2024
1 parent f4b50f7 commit 728c4ba
Show file tree
Hide file tree
Showing 9 changed files with 345 additions and 44 deletions.
6 changes: 5 additions & 1 deletion cilly/src/v2/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,11 @@ impl ClassDef {
}

pub(crate) fn add_def(&mut self, ref_idx: MethodDefIdx) {
assert!(!self.methods.iter().any(|def| *def == ref_idx));
if self.methods.iter().any(|def| *def == ref_idx) {
// Duplicate, skip I guess?
// TODO: check if this duplicate matches the current function.
return;
}
self.methods_mut().push(ref_idx);
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/binop/checked/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ pub fn zero(ty: Ty) -> CILNode {
TyKind::Int(IntTy::I8) => CILNode::LdcI8(0),
TyKind::Uint(UintTy::U64) => ldc_u64!(0),
TyKind::Int(IntTy::I64) => ldc_i64!(0),
TyKind::Uint(UintTy::Usize) => conv_usize!(size_of!(Type::USize)),
TyKind::Int(IntTy::Isize) => conv_isize!(size_of!(Type::USize)),
TyKind::Uint(UintTy::Usize) => conv_usize!(ldc_u32!(0)),
TyKind::Int(IntTy::Isize) => conv_isize!(ldc_u32!(0)),
TyKind::Uint(UintTy::U128) => call!(
CallSite::new_extern(
DotnetTypeRef::uint_128(),
Expand Down
63 changes: 63 additions & 0 deletions src/builtin/atomic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,72 @@ crate::add_method_from_trees!(
],
vec![Some("addr".into()), Some("orend".into())]
);
crate::add_method_from_trees!(
interlocked_and_usize,
&[Type::ManagedReference(Box::new(Type::USize)), Type::USize],
Type::USize,
vec![
BasicBlock::new(
vec![
CILRoot::BEq {
target: 1,
sub_target: 0,
a: Box::new(size_of!(Type::USize)),
b: Box::new(size_of!(Type::U32))
}
.into(),
CILRoot::Ret {
tree: conv_usize!(call!(
CallSite::new(
Some(DotnetTypeRef::interlocked()),
"And".into(),
FnSig::new(
&[Type::ManagedReference(Box::new(Type::U64)), Type::U64],
Type::U64
),
true
),
[
CILNode::LDArg(0).cast_ptr(Type::ManagedReference(Box::new(Type::U64))),
conv_u64!(CILNode::LDArg(1))
]
))
}
.into(),
],
0,
None
),
// sizeof::<usize>() == sizeof::<u32>()
BasicBlock::new(
vec![CILRoot::Ret {
tree: conv_usize!(call!(
CallSite::new(
Some(DotnetTypeRef::interlocked()),
"And".into(),
FnSig::new(
&[Type::ManagedReference(Box::new(Type::U32)), Type::U32],
Type::U32
),
true
),
[
CILNode::LDArg(0).cast_ptr(Type::ManagedReference(Box::new(Type::U32))),
conv_u32!(CILNode::LDArg(1))
]
))
}
.into(),],
1,
None
)
],
vec![Some("addr".into()), Some("andend".into())]
);
pub fn atomics(asm: &mut Assembly) {
interlocked_add_usize(asm);
interlocked_or_usize(asm);
interlocked_and_usize(asm);
interlocked_emulate_xchng_byte(asm);
}
crate::add_method_from_trees!(
Expand Down
38 changes: 37 additions & 1 deletion src/terminator/intrinsics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use rustc_middle::{
use rustc_span::source_map::Spanned;
use saturating::{saturating_add, saturating_sub};
use type_info::{is_val_statically_known, size_of_val};
use utilis::{compare_bytes, interlocked_add, interlocked_or};
use utilis::{compare_bytes, interlocked_add, interlocked_and, interlocked_or, interlocked_xor};
mod bswap;
mod interop;
mod ints;
Expand Down Expand Up @@ -487,6 +487,32 @@ pub fn handle_intrinsic<'tcx>(

place_set(destination, interlocked_or(dst, orand, src_type), ctx)
}
"atomic_xor_seqcst" | "atomic_xor_release" | "atomic_xor_acqrel" | "atomic_xor_acquire"
| "atomic_xor_relaxed" => {
// *T
let dst = handle_operand(&args[0].node, ctx);
// T
let xorand = handle_operand(&args[1].node, ctx);
// we sub by adding a negative number

let src_type = ctx.monomorphize(args[1].node.ty(ctx.body(), ctx.tcx()));
let src_type = ctx.type_from_cache(src_type);

place_set(destination, interlocked_xor(dst, xorand, src_type), ctx)
}
"atomic_and_seqcst" | "atomic_and_release" | "atomic_and_acqrel" | "atomic_and_acquire"
| "atomic_and_relaxed" => {
// *T
let dst = handle_operand(&args[0].node, ctx);
// T
let andand = handle_operand(&args[1].node, ctx);
// we sub by adding a negative number

let src_type = ctx.monomorphize(args[1].node.ty(ctx.body(), ctx.tcx()));
let src_type = ctx.type_from_cache(src_type);

place_set(destination, interlocked_and(dst, andand, src_type), ctx)
}
"atomic_fence_acquire"
| "atomic_fence_seqcst"
| "atomic_fence_release"
Expand Down Expand Up @@ -1240,6 +1266,16 @@ fn intrinsic_slow<'tcx>(
]
.into(),
}
} else if fn_name.contains("type_name") {
let const_val = ctx
.tcx()
.const_eval_instance(ParamEnv::reveal_all(), call_instance, span)
.unwrap();
place_set(
destination,
crate::constant::load_const_value(const_val, Ty::new_static_str(ctx.tcx()), ctx),
ctx,
)
} else {
todo!("Unhandled intrinsic {fn_name}.")
}
Expand Down
118 changes: 118 additions & 0 deletions src/terminator/intrinsics/utilis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,124 @@ pub fn interlocked_or(addr: CILNode, addend: CILNode, tpe: Type) -> CILNode {
_ => todo!(),
}
}
pub fn interlocked_xor(addr: CILNode, addend: CILNode, tpe: Type) -> CILNode {
match tpe {
/*Type::U64 | Type::I64 => {
call!(
CallSite::new(
Some(DotnetTypeRef::interlocked()),
"Or".into(),
FnSig::new(
&[Type::ManagedReference(Box::new(Type::U64)), Type::U64],
Type::U64
),
true
),
[addr, addend]
)
}
Type::U32 | Type::I32 => {
call!(
CallSite::new(
Some(DotnetTypeRef::interlocked()),
"Or".into(),
FnSig::new(
&[Type::ManagedReference(Box::new(Type::U32)), Type::U32],
Type::U32
),
true
),
[addr, addend]
)
}*/
Type::USize | Type::ISize => call!(
CallSite::builtin(
"interlocked_xor_usize".into(),
FnSig::new(
&[Type::ManagedReference(Box::new(Type::USize)), Type::USize],
Type::USize
),
true
),
[addr, addend]
),
Type::Ptr(inner) => call!(
CallSite::builtin(
"interlocked_xor_usize".into(),
FnSig::new(
&[Type::ManagedReference(Box::new(Type::USize)), Type::USize],
Type::USize
),
true
),
[
addr.cast_ptr(Type::ManagedReference(Box::new(Type::USize))),
addend.cast_ptr(Type::USize)
]
)
.cast_ptr(ptr!(*inner)),
_ => todo!(),
}
}
pub fn interlocked_and(addr: CILNode, addend: CILNode, tpe: Type) -> CILNode {
match tpe {
Type::U64 | Type::I64 => {
call!(
CallSite::new(
Some(DotnetTypeRef::interlocked()),
"And".into(),
FnSig::new(
&[Type::ManagedReference(Box::new(Type::U64)), Type::U64],
Type::U64
),
true
),
[addr, addend]
)
}
Type::U32 | Type::I32 => {
call!(
CallSite::new(
Some(DotnetTypeRef::interlocked()),
"And".into(),
FnSig::new(
&[Type::ManagedReference(Box::new(Type::U32)), Type::U32],
Type::U32
),
true
),
[addr, addend]
)
}
Type::USize | Type::ISize => call!(
CallSite::builtin(
"interlocked_and_usize".into(),
FnSig::new(
&[Type::ManagedReference(Box::new(Type::USize)), Type::USize],
Type::USize
),
true
),
[addr, addend]
),
Type::Ptr(inner) => call!(
CallSite::builtin(
"interlocked_and_usize".into(),
FnSig::new(
&[Type::ManagedReference(Box::new(Type::USize)), Type::USize],
Type::USize
),
true
),
[
addr.cast_ptr(Type::ManagedReference(Box::new(Type::USize))),
addend.cast_ptr(Type::USize)
]
)
.cast_ptr(ptr!(*inner)),
_ => todo!(),
}
}
pub fn compare_bytes(a: CILNode, b: CILNode, len: CILNode) -> CILNode {
call!(
CallSite::builtin(
Expand Down
4 changes: 2 additions & 2 deletions src/utilis/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,9 +319,9 @@ pub fn requries_align_adjustement<'tcx>(
ty: rustc_middle::ty::Ty<'tcx>,
tcx: TyCtxt<'tcx>,
) -> Option<u64> {
//TODO: some types requre aligement smaller than 16 bytes but larger than their size. Handle that. Requires reimplemting .NETs algiement clacualtions.
//TODO: some types requre aligement smaller than 16 bytes but larger than their size. Handle that. Requires reimplementing .NETs algiement clacualtions.
let align = align_of(ty, tcx);
if align > 16 {
if align > 8 {
Some(align)
} else {
None
Expand Down
Loading

0 comments on commit 728c4ba

Please sign in to comment.