Skip to content

Commit

Permalink
Some work on converting panics to maanged excpetion
Browse files Browse the repository at this point in the history
  • Loading branch information
FractalFir committed Aug 7, 2024
1 parent 1dddbdc commit 235e30e
Show file tree
Hide file tree
Showing 24 changed files with 373 additions and 145 deletions.
7 changes: 7 additions & 0 deletions cargo_tests/build_std/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ fn should_pass() {}
fn should_panic() {
panic!();
}
#[test]
#[should_panic]
fn div_by_zero() {
let zero = std::hint::black_box(0);
let res = 64 / zero;
std::hint::black_box(res);
}
fn main() {
println!("Hi!");
for arg in std::env::args() {
Expand Down
17 changes: 1 addition & 16 deletions cilly/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,22 +271,7 @@ lazy_static! {
}).unwrap_or(true)
};
}
fn link_static_initializers(a: Option<&Method>, b: Option<&Method>) -> Option<Method> {
match (a, b) {
(None, None) => None,
(Some(a), None) => Some(a.clone()),
(None, Some(b)) => Some(b.clone()),
(Some(a), Some(b)) => {
let mut merged: Method = a.clone();
let mut blocks = merged.blocks_mut();
let trees = blocks[0].trees_mut();
trees.pop();
trees.extend(b.blocks()[0].trees().iter().cloned());
drop(blocks);
Some(merged)
}
}
}

impl MemoryUsage for Assembly {
fn memory_usage(&self, counter: &mut impl crate::utilis::MemoryUsageCounter) -> usize {
let self_size = std::mem::size_of::<Self>();
Expand Down
9 changes: 1 addition & 8 deletions cilly/src/basic_block.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
use std::ops::DerefMut;

use fxhash::{FxBuildHasher, FxHashSet};
use serde::{Deserialize, Serialize};

use crate::{
asm::CILLY_V2,
cil_iter::{CILIterElem, CILIterTrait},
cil_node::{CILNode, ValidationContext},
cil_root::CILRoot,
cil_tree::CILTree,
cil_iter::CILIterElem, cil_node::ValidationContext, cil_root::CILRoot, cil_tree::CILTree,
utilis::MemoryUsage,
DepthSetting,
};

#[derive(Clone, PartialEq, Serialize, Deserialize, Debug)]
Expand Down
28 changes: 27 additions & 1 deletion cilly/src/bin/linker/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#![deny(unused_must_use)]
#![allow(clippy::module_name_repetitions)]
use cilly::{
asm::DEAD_CODE_ELIMINATION,
call_site::CallSite,
conv_usize,
libc_fns::{LIBC_FNS, LIBC_MODIFIES_ERRNO},
Expand Down Expand Up @@ -300,11 +301,36 @@ fn main() {
MethodImpl::MethodBody { blocks, locals }
}),
);
overrides.insert(
final_assembly.alloc_string("_Unwind_DeleteException"),
Box::new(|_, asm| {
let ret = asm.alloc_root(CILRoot::VoidRet);
let blocks = vec![BasicBlock::new(vec![ret], 0, None)];
MethodImpl::MethodBody {
blocks,
locals: vec![],
}
}),
);
overrides.insert(
final_assembly.alloc_string("rust_begin_unwind"),
Box::new(|_, asm| {
MethodImpl::AliasFor(
*asm.find_methods_named("rust_begin_unwind")
.unwrap()
.next()
.unwrap(),
)
}),
);
final_assembly.patch_missing_methods(externs, modifies_errno, overrides);

add_mandatory_statics(&mut final_assembly);
if *DEAD_CODE_ELIMINATION {
println!("Eliminating dead code");
final_assembly.eliminate_dead_code();
}

final_assembly.eliminate_dead_code();
final_assembly
.save_tmp(&mut std::fs::File::create(path.with_extension("cilly2")).unwrap())
.unwrap();
Expand Down
53 changes: 31 additions & 22 deletions cilly/src/cil_iter.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use ordered_float::OrderedFloat;

use crate::{call_site::CallSite, cil_node::CILNode, cil_root::CILRoot};

#[derive(Debug, Clone, Copy)]
Expand Down Expand Up @@ -312,30 +310,39 @@ impl<'a> Iterator for CILIter<'a> {
}
CILIterElem::Node(CILNode::SubTrees(rn)) => {
let (roots, node) = rn.as_ref();
if *idx - 1 < roots.len() {
let root: &CILRoot = &roots[*idx - 1];
*idx += 1;
self.elems.push((0, CILIterElem::Root(root)));
} else if *idx - 1 == roots.len() {
*idx += 1;
self.elems.push((0, CILIterElem::Node(node)));
} else {
self.elems.pop();
match (*idx - 1).cmp(&roots.len()) {
std::cmp::Ordering::Less => {
let root: &CILRoot = &roots[*idx - 1];
*idx += 1;
self.elems.push((0, CILIterElem::Root(root)));
}
std::cmp::Ordering::Equal => {
*idx += 1;
self.elems.push((0, CILIterElem::Node(node)));
}
std::cmp::Ordering::Greater => {
self.elems.pop();
}
}

continue;
}

CILIterElem::Node(CILNode::TemporaryLocal(pack)) => {
let (_, roots, node) = pack.as_ref();
if *idx - 1 < roots.len() {
let root: &CILRoot = &roots[*idx - 1];
*idx += 1;
self.elems.push((0, CILIterElem::Root(root)));
} else if *idx - 1 == roots.len() {
*idx += 1;
self.elems.push((0, CILIterElem::Node(node)));
} else {
self.elems.pop();
match (*idx - 1).cmp(&roots.len()) {
std::cmp::Ordering::Less => {
let root: &CILRoot = &roots[*idx - 1];
*idx += 1;
self.elems.push((0, CILIterElem::Root(root)));
}
std::cmp::Ordering::Equal => {
*idx += 1;
self.elems.push((0, CILIterElem::Node(node)));
}
std::cmp::Ordering::Greater => {
self.elems.pop();
}
}
continue;
}
Expand Down Expand Up @@ -571,7 +578,7 @@ fn iter() {
)),
args: [
CILNode::LdcI32(-77),
CILNode::LdcF32(OrderedFloat(3.119765)),
CILNode::LdcF32(ordered_float::OrderedFloat(3.119765)),
]
.into(),
};
Expand All @@ -586,7 +593,9 @@ fn iter() {
));
assert!(matches!(
iter.next(),
Some(CILIterElem::Node(CILNode::LdcF32(OrderedFloat(3.119765))))
Some(CILIterElem::Node(CILNode::LdcF32(
ordered_float::OrderedFloat(3.119765)
)))
));
assert!(iter.next().is_none());
}
2 changes: 1 addition & 1 deletion cilly/src/cil_node.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
call, call_site::CallSite, cil_iter::CILIterTrait, cil_root::CILRoot,
field_desc::FieldDescriptor, fn_sig::FnSig, ptr, static_field_desc::StaticFieldDescriptor,
AsmStringContainer, DotnetTypeRef, IString, Type,
DotnetTypeRef, IString, Type,
};
use ordered_float::OrderedFloat;
use serde::{Deserialize, Serialize};
Expand Down
2 changes: 0 additions & 2 deletions cilly/src/cil_tree.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use std::borrow::Borrow;

use serde::{Deserialize, Serialize};

use crate::{cil_node::ValidationContext, cil_root::CILRoot, IString, Type};
Expand Down
4 changes: 2 additions & 2 deletions cilly/src/dotnet_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,8 @@ impl DotnetTypeRef {
}
}
#[must_use]
pub fn array(element: &Type, length: usize, strings: &AsmStringContainer) -> Self {
let name = crate::arr_name(length, element, strings);
pub fn array(element: &Type, length: usize) -> Self {
let name = crate::arr_name(length, element);
Self::new::<crate::IString, _>(None, name)
}

Expand Down
22 changes: 8 additions & 14 deletions cilly/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,14 @@ pub mod utilis;
pub mod v2;
#[must_use]
/// Returns the name of a fixed-size array
pub fn arr_name(element_count: usize, element: &Type, strings: &AsmStringContainer) -> IString {
let element_name = mangle(element, strings);
pub fn arr_name(element_count: usize, element: &Type) -> IString {
let element_name = mangle(element);
format!("Arr{element_count}_{element_name}",).into()
}
/// Returns a mangled type name.
/// # Panics
/// Panics when a genetic managed array is used.
pub fn mangle(tpe: &Type, strings: &AsmStringContainer) -> std::borrow::Cow<'static, str> {
pub fn mangle(tpe: &Type) -> std::borrow::Cow<'static, str> {
match tpe {
Type::Bool => "b".into(),
Type::Void => "v".into(),
Expand All @@ -99,32 +99,26 @@ pub fn mangle(tpe: &Type, strings: &AsmStringContainer) -> std::borrow::Cow<'sta
Type::F16 => "f16".into(),
Type::F32 => "f32".into(),
Type::F64 => "f64".into(),
Type::Ptr(inner) => format!("p{inner}", inner = mangle(inner, strings)).into(),
Type::Ptr(inner) => format!("p{inner}", inner = mangle(inner,)).into(),
Type::DotnetType(tpe) => {
assert!(
tpe.generics().is_empty(),
"Arrays of generic .NET types not supported yet"
);
tpe.name_path().replace('.', "_").into()
}
Type::ManagedArray { element, dims } => {
format!("a{}{}", dims, mangle(element, strings)).into()
}
Type::ManagedArray { element, dims } => format!("a{}{}", dims, mangle(element,)).into(),
Type::DotnetChar => "c".into(),
Type::GenericArg(_) => todo!("Can't mangle generic type arg"),

Type::DelegatePtr(sig) => format!(
"d{output}{input_count}{input_string}",
output = mangle(sig.output(), strings),
output = mangle(sig.output(),),
input_count = sig.inputs().len(),
input_string = sig
.inputs()
.iter()
.map(|s| mangle(s, strings))
.collect::<String>()
input_string = sig.inputs().iter().map(|s| mangle(s,)).collect::<String>()
)
.into(),
Type::ManagedReference(inner) => format!("m{inner}", inner = mangle(inner, strings)).into(),
Type::ManagedReference(inner) => format!("m{inner}", inner = mangle(inner,)).into(),
Type::Foreign => "g".into(),
Type::CallGenericArg(_) => "l".into(),
Type::MethodGenericArg(_) => "h".into(),
Expand Down
8 changes: 3 additions & 5 deletions cilly/src/method.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
use fxhash::{FxBuildHasher, FxHashMap, FxHashSet};
use serde::{Deserialize, Serialize};
use std::{
borrow::BorrowMut,
hash::{Hash, Hasher},
ops::{Deref, DerefMut},
};

use crate::{
access_modifier::AccessModifer,
asm::Assembly,
basic_block::BasicBlock,
call_site::CallSite,
cil_iter::{CILIterElem, CILIterTrait},
cil_iter_mut::{CILIterElemMut, CILIterMut, CILIterMutTrait},
cil_iter_mut::CILIterElemMut,
cil_node::{CILNode, ValidationContext},
cil_root::CILRoot,
cil_tree::CILTree,
static_field_desc::StaticFieldDescriptor,
utilis::MemoryUsage,
AsmStringContainer, DepthSetting, DotnetTypeRef, FnSig, IString, Type,
DotnetTypeRef, FnSig, IString, Type,
};

/// Represenation of a CIL method.
Expand Down Expand Up @@ -130,7 +128,7 @@ impl Method {
self.local_sets(local).count()
}
pub fn const_opt_pass(&mut self) {
use crate::cil_iter_mut::{CILIterElemMut, CILIterMutTrait};
use crate::cil_iter_mut::CILIterMutTrait;
// If a local is set only once, and its address is never taken, it is likely to be const
// TODO: this is inefficient Consider checking all locals at once?
let luo = LocalUsageInfo::from_method(self);
Expand Down
2 changes: 1 addition & 1 deletion cilly/src/type_def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ impl TypeDef {
let max_offset = offsets.iter().max().unwrap_or(&0);

assert!(
(*max_offset as u32)
(*max_offset)
< self
.explict_size()
.unwrap_or_else(|| {
Expand Down
1 change: 0 additions & 1 deletion cilly/src/utilis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,6 @@ pub fn assert_unique<T: std::hash::Hash + PartialEq + Eq>(val: &[T], msg: impl D
fn argv() {
let mut asm = Assembly::empty();
argc_argv_init_method(&mut asm);
let mut out = String::new();
}
pub trait MemoryUsage {
fn memory_usage(&self, counter: &mut impl MemoryUsageCounter) -> usize;
Expand Down
20 changes: 18 additions & 2 deletions cilly/src/v2/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,22 @@ pub struct Assembly {
method_defs: FxHashMap<MethodDefIdx, MethodDef>,
}
impl Assembly {
pub fn find_methods_named(
&self,
name: impl Into<IString>,
) -> Option<impl Iterator<Item = MethodDefIdx> + '_> {
let name = self.get_prealllocated_string(name)?;
Some(self.method_defs.iter().filter_map(move |(mdefidx, mdef)| {
if mdef.name() == name {
Some(*mdefidx)
} else {
None
}
}))
}
pub fn get_prealllocated_string(&self, string: impl Into<IString>) -> Option<StringIdx> {
self.strings.1.get(&IStringWrapper(string.into())).copied()
}
pub fn class_mut(&mut self, id: ClassDefIdx) -> &mut ClassDef {
self.class_defs.get_mut(&id).unwrap()
}
Expand Down Expand Up @@ -217,8 +233,8 @@ impl Assembly {
self.class_defs
.get_mut(&def_class)
.expect("Method added without a class")
.methods_mut()
.push(MethodDefIdx(ref_idx));
.add_def(MethodDefIdx(ref_idx));

self.method_defs.insert(MethodDefIdx(ref_idx), def);

MethodDefIdx(ref_idx)
Expand Down
5 changes: 5 additions & 0 deletions cilly/src/v2/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,11 @@ impl ClassDef {
// Check accessibility matches
assert_eq!(self.access(), translated.access());
}

pub(crate) fn add_def(&mut self, ref_idx: MethodDefIdx) {
assert!(!self.methods.iter().any(|def| *def == ref_idx));
self.methods_mut().push(ref_idx);
}
}
#[derive(Hash, PartialEq, Eq, Clone, Debug, Copy, Serialize, Deserialize)]
pub struct ClassDefIdx(pub ClassRefIdx);
Expand Down
4 changes: 2 additions & 2 deletions cilly/src/v2/il_exporter/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::io::Write;
use lazy_static::*;
use crate::{ utilis::assert_unique, v2::MethodImpl, };
use crate::v2::MethodImpl;

use super::{
asm::{IlasmFlavour, ILASM_FLAVOUR, ILASM_PATH}, cilroot::BranchCond, int, Assembly, CILIter, CILIterElem, CILNode, ClassRefIdx, Exporter, NodeIdx, RootIdx, Type
Expand Down Expand Up @@ -128,7 +128,7 @@ impl ILExporter {
out,
".method {vis} hidebysig {kind} {pinvoke} {ret} '{name}'({inputs}) cil managed {preservesig}{{// Method ID {method_id:?}"
)?;
let stack_size = match method.implementation() {
let stack_size = match method.resolved_implementation(asm) {
MethodImpl::MethodBody { blocks, .. } => blocks
.iter()
.flat_map(|block| block.roots().iter())
Expand Down
3 changes: 1 addition & 2 deletions src/aggregate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,7 @@ pub fn handle_aggregate<'tcx>(
AggregateKind::Array(element) => {
let element = ctx.monomorphize(*element);
let element = ctx.type_from_cache(element);
let array_type =
DotnetTypeRef::array(&element, value_index.len(), &AsmStringContainer::default());
let array_type = DotnetTypeRef::array(&element, value_index.len());
let array_getter = super::place::place_adress(target_location, ctx);
let sig = cilly::fn_sig::FnSig::new(
&[ptr!(array_type.clone().into()), Type::USize, element],
Expand Down
Loading

0 comments on commit 235e30e

Please sign in to comment.