Skip to content

Commit aad2cac

Browse files
committed
Fixed fmin and fmax intrinsics.
1 parent 53a2943 commit aad2cac

File tree

18 files changed

+336
-47
lines changed

18 files changed

+336
-47
lines changed

cargo_tests/build_std/Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ edition = "2021"
77

88
[dependencies]
99
mycorrhiza = {path="../../mycorrhiza"}
10+
rand = "0.8.5"
1011
[workspace]
1112
[profile.release.build-override]
12-
codegen-units = 1
13+
codegen-units = 1

cargo_tests/build_std/src/main.rs

+113-10
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,119 @@ fn should_pass() {}
55
fn should_panic() {
66
panic!();
77
}
8-
#[test]
9-
#[should_panic]
10-
fn div_by_zero() {
11-
let zero = std::hint::black_box(0);
12-
let res = 64 / zero;
13-
std::hint::black_box(res);
14-
}
158
fn main() {
16-
println!("Hi!");
17-
for arg in std::env::args() {
18-
println!("arg:{arg:?}");
9+
select_nth_unstable();
10+
}
11+
12+
fn select_nth_unstable() {
13+
use core::cmp::Ordering::{Equal, Greater, Less};
14+
15+
use rand::seq::SliceRandom;
16+
use rand::Rng;
17+
let mut rng = rand::thread_rng();
18+
let mut v = [0; 500];
19+
for pivot in 0..v.len() {
20+
println!("{}:{}", file!(), line!());
21+
v.select_nth_unstable_by(pivot, |_, _| {
22+
*[Less, Equal, Greater].choose(&mut rng).unwrap()
23+
});
24+
v.sort();
25+
for i in 0..v.len() {
26+
println!("{}:{}", file!(), line!());
27+
assert_eq!(v[i], i as i32);
28+
}
29+
}
30+
31+
for len in (2..21).chain(500..501) {
32+
let mut orig = vec![0; len];
33+
println!("{}:{}", file!(), line!());
34+
for &modulus in &[5, 10, 1000] {
35+
for _ in 0..10 {
36+
println!("{}:{}", file!(), line!());
37+
for i in 0..len {
38+
println!("{}:{}", file!(), line!());
39+
orig[i] = rng.gen::<i32>() % modulus;
40+
}
41+
42+
let v_sorted = {
43+
let mut v = orig.clone();
44+
v.sort();
45+
v
46+
};
47+
48+
// Sort in default order.
49+
for pivot in 0..len {
50+
println!("{}:{}", file!(), line!());
51+
let mut v = orig.clone();
52+
v.select_nth_unstable(pivot);
53+
54+
assert_eq!(v_sorted[pivot], v[pivot]);
55+
for i in 0..pivot {
56+
for j in pivot..len {
57+
assert!(v[i] <= v[j]);
58+
}
59+
}
60+
}
61+
62+
// Sort in ascending order.
63+
for pivot in 0..len {
64+
println!("{}:{}", file!(), line!());
65+
let mut v = orig.clone();
66+
let (left, pivot, right) = v.select_nth_unstable_by(pivot, |a, b| a.cmp(b));
67+
68+
assert_eq!(left.len() + right.len(), len - 1);
69+
70+
for l in left {
71+
assert!(l <= pivot);
72+
for r in right.iter_mut() {
73+
assert!(l <= r);
74+
assert!(pivot <= r);
75+
}
76+
}
77+
}
78+
79+
// Sort in descending order.
80+
let sort_descending_comparator = |a: &i32, b: &i32| b.cmp(a);
81+
let v_sorted_descending = {
82+
let mut v = orig.clone();
83+
v.sort_by(sort_descending_comparator);
84+
v
85+
};
86+
87+
for pivot in 0..len {
88+
println!("{}:{}", file!(), line!());
89+
let mut v = orig.clone();
90+
v.select_nth_unstable_by(pivot, sort_descending_comparator);
91+
92+
assert_eq!(v_sorted_descending[pivot], v[pivot]);
93+
for i in 0..pivot {
94+
for j in pivot..len {
95+
assert!(v[j] <= v[i]);
96+
}
97+
}
98+
}
99+
}
100+
}
101+
}
102+
103+
// Sort at index using a completely random comparison function.
104+
// This will reorder the elements *somehow*, but won't panic.
105+
let mut v = [0; 500];
106+
for i in 0..v.len() {
107+
println!("{}:{}", file!(), line!());
108+
v[i] = i as i32;
19109
}
110+
111+
// Should not panic.
112+
[(); 10].select_nth_unstable(0);
113+
[(); 10].select_nth_unstable(5);
114+
[(); 10].select_nth_unstable(9);
115+
[(); 100].select_nth_unstable(0);
116+
[(); 100].select_nth_unstable(50);
117+
[(); 100].select_nth_unstable(99);
118+
119+
let mut v = [0xDEADBEEFu64];
120+
v.select_nth_unstable(0);
121+
assert!(v == [0xDEADBEEF]);
122+
println!("v:{v:?}");
20123
}

cilly/src/bin/linker/main.rs

+26-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ use cilly::{
88
v2::{
99
asm::{MissingMethodPatcher, ILASM_FLAVOUR},
1010
cilnode::MethodKind,
11-
BasicBlock, CILNode, CILRoot, ClassRef, IlasmFlavour, Int, MethodImpl, Type,
11+
Assembly, BasicBlock, CILNode, CILRoot, ClassRef, Const, IlasmFlavour, Int, MethodImpl,
12+
Type,
1213
},
1314
DotnetTypeRef, FnSig,
1415
};
@@ -178,8 +179,24 @@ fn main() {
178179
.iter()
179180
.map(|fn_name| (*fn_name, LIBC.as_ref()))
180181
.collect();
182+
181183
let modifies_errno = LIBC_MODIFIES_ERRNO.iter().copied().collect();
182184
let mut overrides: MissingMethodPatcher = FxHashMap::default();
185+
overrides.insert(
186+
final_assembly.alloc_string("pthread_atfork"),
187+
Box::new(|_, asm: &mut Assembly| {
188+
let ret_val = asm.alloc_node(Const::I32(0));
189+
let blocks = vec![BasicBlock::new(
190+
vec![asm.alloc_root(CILRoot::Ret(ret_val))],
191+
1,
192+
None,
193+
)];
194+
MethodImpl::MethodBody {
195+
blocks,
196+
locals: vec![],
197+
}
198+
}),
199+
);
183200
// Override allocator
184201
{
185202
// Get the marshal class
@@ -401,6 +418,14 @@ fn main() {
401418
//todo!();
402419
}
403420
fn bootstrap_source(fpath: &Path, output_file_path: &str, jumpstart_cmd: &str) -> String {
421+
if let Err(err) = std::fs::remove_file(output_file_path) {
422+
match err.kind() {
423+
std::io::ErrorKind::NotFound => (),
424+
_ => {
425+
panic!("Could not remove tmp file because {err:?}")
426+
}
427+
}
428+
};
404429
format!(
405430
include_str!("dotnet_jumpstart.rs"),
406431
jumpstart_cmd = jumpstart_cmd,

cilly/src/libc_fns.rs

-1
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,6 @@ pub const LIBC_FNS: &[&str] = &[
312312
"prlimit",
313313
"psiginfo",
314314
"psignal",
315-
"pthread_atfork",
316315
"ptrace",
317316
"ptsname",
318317
"putchar",

cilly/src/type.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ impl Type {
113113
| Self::USize => true,
114114
Self::Bool => true,
115115
Self::F32 | Self::F64 => true,
116-
Self::Ptr(_) => true,
116+
Self::Ptr(_) | Self::DelegatePtr(_) => true,
117117
// 128 bit ints are NOT primitve CIL types!
118118
Self::I128 | Self::U128 => true,
119119
_ => false,

cilly/src/type_def.rs

+14-11
Original file line numberDiff line numberDiff line change
@@ -132,18 +132,21 @@ impl TypeDef {
132132
name = self.name()
133133
);
134134
let max_offset = offsets.iter().max().unwrap_or(&0);
135-
135+
let explict_size = self
136+
.explict_size()
137+
.unwrap_or_else(|| {
138+
panic!(
139+
"Explict offsets provided without explicit size. Type: {}",
140+
self.name()
141+
)
142+
})
143+
.get();
136144
assert!(
137-
(*max_offset)
138-
< self
139-
.explict_size()
140-
.unwrap_or_else(|| {
141-
panic!(
142-
"Explict offsets provided without explicit size. Type: {}",
143-
self.name()
144-
)
145-
})
146-
.get()
145+
(*max_offset) < explict_size,
146+
"name:{:?} max_offset:{max_offset} explict_size:{explict_size} offsets:{:?} fields:{:?}",
147+
self.name(),
148+
self.explicit_offsets().unwrap(),
149+
self.fields()
147150
);
148151
}
149152
self.field_types()

cilly/src/v2/il_exporter/mod.rs

+19-1
Original file line numberDiff line numberDiff line change
@@ -994,12 +994,30 @@ impl Exporter for ILExporter {
994994
fn export(&self, asm: &super::Assembly, target: &std::path::Path) -> Result<(), Self::Error> {
995995
// The IL file should be next to the target
996996
let il_path = target.with_extension("il");
997+
998+
if let Err(err) = std::fs::remove_file(&il_path) {
999+
match err.kind() {
1000+
std::io::ErrorKind::NotFound => (),
1001+
_ => {
1002+
panic!("Could not remove tmp file because {err:?}")
1003+
}
1004+
}
1005+
};
9971006
let mut il_out = std::io::BufWriter::new(std::fs::File::create(&il_path)?);
9981007
self.export_to_write(asm, &mut il_out)?;
9991008
// Needed to ensure the IL file is valid!
10001009
il_out.flush().unwrap();
10011010
drop(il_out);
10021011
let exe_out = target.with_extension("exe");
1012+
1013+
if let Err(err) = std::fs::remove_file(&exe_out) {
1014+
match err.kind() {
1015+
std::io::ErrorKind::NotFound => (),
1016+
_ => {
1017+
panic!("Could not remove tmp file because {err:?}")
1018+
}
1019+
}
1020+
};
10031021
let asm_type = if self.is_lib { "-dll" } else { "-exe" };
10041022
let mut cmd = std::process::Command::new(ILASM_PATH.clone());
10051023
cmd.arg(il_path)
@@ -1097,7 +1115,7 @@ fn type_il(tpe: &Type, asm: &Assembly) -> String {
10971115
},
10981116
Type::ClassRef(cref) => class_ref(*cref, asm),
10991117
Type::Float(float) => match float {
1100-
super::Float::F16 => todo!(),
1118+
super::Float::F16 => "valuetype [System.Runtime]System.Half".into(),
11011119
super::Float::F32 => "float32".into(),
11021120
super::Float::F64 => "float64".into(),
11031121
},

src/aggregate.rs

+7
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@ pub fn handle_aggregate<'tcx>(
6060
)
6161
}
6262
AggregateKind::Array(element) => {
63+
// Check if this array is made up from uninit values
64+
if crate::operand::is_uninit(&value_index[FieldIdx::from_usize(0)], ctx) {
65+
// This array is created from uninitalized data, so it itsefl is uninitialzed, so we can skip initializing it.
66+
return super::place::place_get(target_location, ctx);
67+
}
68+
6369
let element = ctx.monomorphize(*element);
6470
let element = ctx.type_from_cache(element);
6571
let array_type = DotnetTypeRef::array(&element, value_index.len());
@@ -81,6 +87,7 @@ pub fn handle_aggregate<'tcx>(
8187
.into(),
8288
});
8389
}
90+
8491
CILNode::SubTrees(Box::new((
8592
sub_trees.into(),
8693
Box::new(super::place::place_get(target_location, ctx)),

src/bin/autotest.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ fn main() {
2727
let stderr = str::from_utf8(&out.stderr).unwrap().to_string();
2828
let stdout = str::from_utf8(&out.stdout).unwrap().to_string();
2929
for line in stdout.lines() {
30-
if !line.contains("test ") {
30+
if !line.contains("test ") || line.contains("finished in") {
3131
continue;
3232
}
3333
let mut split = line.split("...");
@@ -39,14 +39,15 @@ fn main() {
3939
let name = name["test ".len()..].trim();
4040
let name = name.split("-").next().unwrap().trim();
4141
let status = split.next().unwrap_or("");
42+
4243
if status.contains("ok") {
4344
ok.insert(name.to_owned());
4445
} else if status.contains("FAILED") {
4546
failures.insert(name.to_owned());
46-
} else {
47-
if !broken.iter().any(|exisitng| exisitng == name) {
48-
broken.push(name.to_owned());
49-
}
47+
} else if status.contains("ignored") {
48+
continue;
49+
} else if !broken.iter().any(|exisitng| exisitng == name) {
50+
broken.push(name.to_owned());
5051
}
5152
}
5253
if stderr.contains("failures:")

src/binop/cmp.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ pub fn lt_unchecked(ty_a: Ty<'_>, operand_a: CILNode, operand_b: CILNode) -> CIL
7070
},
7171
// TODO: are chars considered signed or unsigned?
7272
TyKind::Bool | TyKind::Char | TyKind::Float(_) => lt!(operand_a, operand_b),
73-
TyKind::RawPtr(_, _) => lt_un!(operand_a, operand_b),
73+
TyKind::RawPtr(_, _) | TyKind::FnPtr(_) => lt_un!(operand_a, operand_b),
7474
_ => panic!("Can't eq type {ty_a:?}"),
7575
}
7676
}

src/constant.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ fn load_const_scalar<'tcx>(
407407
}
408408
}
409409
}
410-
TyKind::Adt(_, _subst) => CILNode::LdObj {
410+
TyKind::Adt(_, _) | TyKind::Closure(_, _) => CILNode::LdObj {
411411
ptr: Box::new(
412412
CILNode::PointerToConstValue(Box::new(scalar_u128))
413413
.cast_ptr(ptr!(scalar_type.clone())),

0 commit comments

Comments
 (0)