Skip to content

Commit dd19b99

Browse files
committed
Switched overflow checks away from tmp locals.
1 parent 2d5df20 commit dd19b99

File tree

10 files changed

+168
-60
lines changed

10 files changed

+168
-60
lines changed

cilly/src/bin/linker/main.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,9 @@ fn main() {
447447
cilly::v2::builtins::stack_addr(&mut final_assembly, &mut overrides);
448448
cilly::v2::builtins::transmute(&mut final_assembly, &mut overrides);
449449
cilly::v2::builtins::create_slice(&mut final_assembly, &mut overrides);
450+
cilly::v2::builtins::ovf_check_tuple(&mut final_assembly, &mut overrides);
451+
cilly::v2::builtins::uninit_val(&mut final_assembly, &mut overrides);
452+
450453
cilly::v2::builtins::math::bitreverse(&mut final_assembly, &mut overrides);
451454

452455
if *C_MODE {

cilly/src/cil_node.rs

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,16 @@ impl CILNode {
240240
val: Self,
241241
tpe: Type,
242242
) -> CILNode {
243-
let item2 = asm.alloc_string("Item2");
243+
let main = asm.main_module();
244+
let sig = asm.sig([tpe, Type::Bool], Type::ClassRef(tuple));
245+
let site = asm.new_methodref(*main, "ovf_check_tuple", sig, MethodKind::Static, []);
246+
CILNode::Call(Box::new(CallOpArgs {
247+
args: vec![val, out_of_range].into(),
248+
site,
249+
is_pure: IsPure::PURE,
250+
}))
251+
/*
252+
let item2 = asm.alloc_string("Item2");
244253
let item1 = asm.alloc_string("Item1");
245254
CILNode::TemporaryLocal(Box::new((
246255
asm.alloc_type(tuple),
@@ -258,7 +267,7 @@ impl CILNode {
258267
]
259268
.into(),
260269
CILNode::LoadTMPLocal,
261-
)))
270+
)))*/
262271
}
263272
pub fn create_slice(
264273
slice_tpe: ClassRefIdx,
@@ -268,9 +277,13 @@ impl CILNode {
268277
) -> Self {
269278
let void_ptr = asm.nptr(Type::Void);
270279
let main = asm.main_module();
271-
let sig = asm.sig([void_ptr,Type::Int(Int::USize)],Type::ClassRef(slice_tpe));
280+
let sig = asm.sig([void_ptr, Type::Int(Int::USize)], Type::ClassRef(slice_tpe));
272281
let create_slice = asm.new_methodref(*main, "create_slice", sig, MethodKind::Static, []);
273-
CILNode::Call(Box::new(CallOpArgs { args: vec![ptr, metadata].into(), site: create_slice, is_pure: IsPure::PURE }))
282+
CILNode::Call(Box::new(CallOpArgs {
283+
args: vec![ptr, metadata].into(),
284+
site: create_slice,
285+
is_pure: IsPure::PURE,
286+
}))
274287
}
275288
pub fn const_u128(value: u128, asm: &mut Assembly) -> CILNode {
276289
CILNode::V2(asm.alloc_node(value))
@@ -298,7 +311,6 @@ impl CILNode {
298311
);
299312
call!(asm.alloc_methodref(mref), [gc_handle])
300313
}
301-
302314

303315
#[must_use]
304316
pub fn select(tpe: Type, a: Self, b: Self, predictate: Self, asm: &mut Assembly) -> Self {
@@ -356,11 +368,18 @@ impl CILNode {
356368

357369
/// Creates an unintialized value of type *tpe*.
358370
pub fn uninit_val(tpe: Type, asm: &mut Assembly) -> Self {
359-
CILNode::TemporaryLocal(Box::new((
360-
asm.alloc_type(tpe),
361-
[].into(),
362-
CILNode::LoadTMPLocal,
363-
)))
371+
if tpe == Type::Void{
372+
let gv = asm.global_void();
373+
return CILNode::LDStaticField(Box::new(asm[gv]));
374+
}
375+
let main = asm.main_module();
376+
let sig = asm.sig([], tpe);
377+
let uninit_val = asm.new_methodref(*main, "uninit_val", sig, MethodKind::Static, []);
378+
CILNode::Call(Box::new(CallOpArgs {
379+
args: [].into(),
380+
site: uninit_val,
381+
is_pure: IsPure::PURE,
382+
}))
364383
}
365384
pub fn transmute_on_stack(self, src: Type, target: Type, asm: &mut Assembly) -> Self {
366385
let main_module = *asm.main_module();
@@ -372,7 +391,6 @@ impl CILNode {
372391
site: mref,
373392
is_pure: crate::v2::cilnode::IsPure::NOT,
374393
}))
375-
376394
}
377395
pub fn cxchng_res_val(
378396
old_val: Self,

cilly/src/v2/asm.rs

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,7 @@ impl Assembly {
405405
let cref = self.alloc_class_ref(cref);
406406

407407
if self.class_defs.contains_key(&ClassDefIdx(cref)) {
408-
if self[def.name()].contains("core.ffi.c_void") {
408+
if self[def.name()].contains("core.ffi.c_void") || self[def.name()].contains("RustVoid") {
409409
return ClassDefIdx(cref);
410410
}
411411
panic!()
@@ -695,12 +695,9 @@ impl Assembly {
695695
pub fn save_tmp<W: std::io::Write>(&self, w: &mut W) -> std::io::Result<()> {
696696
w.write_all(&postcard::to_stdvec(&self).unwrap())
697697
}
698-
/// Converts the old assembly repr to the new one.
699-
#[must_use]
700-
pub fn from_v1(v1: &Assembly) -> Self {
701-
let mut empty: Assembly = v1.clone();
702-
let rust_void = empty.alloc_string("RustVoid");
703-
empty.class_def(ClassDef::new(
698+
pub(crate) fn rust_void(&mut self)->ClassDefIdx{
699+
let rust_void = self.alloc_string("RustVoid");
700+
self.class_def(ClassDef::new(
704701
rust_void,
705702
true,
706703
0,
@@ -711,7 +708,13 @@ impl Assembly {
711708
None,
712709
None,
713710
true,
714-
));
711+
))
712+
}
713+
/// Converts the old assembly repr to the new one.
714+
#[must_use]
715+
pub fn from_v1(v1: &Assembly) -> Self {
716+
let mut empty: Assembly = v1.clone();
717+
empty.rust_void();
715718

716719
#[cfg(debug_assertions)]
717720
empty.sanity_check();
@@ -1320,17 +1323,22 @@ impl Assembly {
13201323
pub(crate) fn get_section(&self, arg: &str) -> Option<&Vec<u8>> {
13211324
self.sections.get(arg)
13221325
}
1323-
1326+
13241327
pub(crate) fn guaranted_align(&self) -> u8 {
13251328
*GUARANTED_ALIGN
13261329
}
1327-
1330+
13281331
pub fn max_static_size(&self) -> usize {
13291332
*MAX_STATIC_SIZE
13301333
}
1334+
1335+
pub(crate) fn global_void(&mut self) ->StaticFieldIdx {
1336+
let main = self.main_module();
1337+
self.add_static(Type::Void, "global_void", false, main)
1338+
}
13311339
}
1332-
config!(GUARANTED_ALIGN, u8,8);
1333-
config!(MAX_STATIC_SIZE, usize,16);
1340+
config!(GUARANTED_ALIGN, u8, 8);
1341+
config!(MAX_STATIC_SIZE, usize, 16);
13341342
/// An initializer, which runs before everything else. By convention, it is used to initialize static / const data. Should not execute any user code
13351343
pub const CCTOR: &str = ".cctor";
13361344
/// An thread-local initializer. Runs before each thread starts. By convention, it is used to initialize thread local data. Should not execute any user code.

cilly/src/v2/builtins/mod.rs

Lines changed: 67 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ use std::num::{NonZeroU32, NonZeroU8};
33
use crate::{utilis::mstring_to_utf8ptr, IntoAsmIndex, StaticFieldDesc};
44

55
use super::{
6-
asm::MissingMethodPatcher, cilnode::{MethodKind, PtrCastRes}, cilroot::BranchCond, Access, Assembly, BasicBlock, CILNode, CILRoot, ClassDef, ClassRef, Const, FieldDesc, FieldIdx, Int, MethodDef, MethodImpl, MethodRef, MethodRefIdx, Type
6+
asm::MissingMethodPatcher,
7+
cilnode::{MethodKind, PtrCastRes},
8+
cilroot::BranchCond,
9+
Access, Assembly, BasicBlock, CILNode, CILRoot, ClassDef, ClassRef, Const, FieldDesc, FieldIdx,
10+
Int, MethodDef, MethodImpl, MethodRef, MethodRefIdx, Type,
711
};
812

913
pub mod atomics;
@@ -154,27 +158,78 @@ fn insert_rust_alloc_zeroed(asm: &mut Assembly, patcher: &mut MissingMethodPatch
154158
};
155159
patcher.insert(name, Box::new(generator));
156160
}
161+
162+
pub fn uninit_val(asm: &mut Assembly, patcher: &mut MissingMethodPatcher) {
163+
let name = asm.alloc_string("uninit_val");
164+
let generator = move |mref:MethodRefIdx, asm: &mut Assembly| {
165+
let ret = asm.alloc_node(CILNode::LdLoc(0));
166+
let res = *asm[asm[mref].sig()].output();
167+
MethodImpl::MethodBody {
168+
blocks: vec![BasicBlock::new(
169+
vec![asm.alloc_root(CILRoot::Ret(ret))],
170+
0,
171+
None,
172+
)],
173+
locals: vec![(None, asm.alloc_type(res))],
174+
}
175+
};
176+
177+
patcher.insert(name, Box::new(generator));
178+
}
179+
pub fn ovf_check_tuple(asm: &mut Assembly, patcher: &mut MissingMethodPatcher) {
180+
let name = asm.alloc_string("ovf_check_tuple");
181+
let generator = move |mref: MethodRefIdx, asm: &mut Assembly| {
182+
let res = *asm[asm[mref].sig()].output();
183+
let addr = asm.alloc_node(CILNode::LdLocA(0));
184+
let arg0 = asm.alloc_node(CILNode::LdArg(0));
185+
let arg1 = asm.alloc_node(CILNode::LdArg(1));
186+
let ret = asm.alloc_node(CILNode::LdLoc(0));
187+
let item1 = asm.alloc_string("Item1");
188+
let item2 = asm.alloc_string("Item2");
189+
let tpe = asm[asm[mref].sig()].inputs()[0];
190+
let item1 = asm.alloc_field(FieldDesc::new(res.as_class_ref().unwrap(), item1, tpe));
191+
let item2 = asm.alloc_field(FieldDesc::new(
192+
res.as_class_ref().unwrap(),
193+
item2,
194+
Type::Bool,
195+
));
196+
MethodImpl::MethodBody {
197+
blocks: vec![BasicBlock::new(
198+
vec![
199+
asm.alloc_root(CILRoot::SetField(Box::new((item1, addr, arg0)))),
200+
asm.alloc_root(CILRoot::SetField(Box::new((item2, addr, arg1)))),
201+
asm.alloc_root(CILRoot::Ret(ret)),
202+
],
203+
0,
204+
None,
205+
)],
206+
locals: vec![(None, asm.alloc_type(res))],
207+
}
208+
};
209+
patcher.insert(name, Box::new(generator));
210+
}
157211
pub fn create_slice(asm: &mut Assembly, patcher: &mut MissingMethodPatcher) {
158212
let name = asm.alloc_string("create_slice");
159-
let generator = move |mref:MethodRefIdx, asm: &mut Assembly| {
213+
let generator = move |mref: MethodRefIdx, asm: &mut Assembly| {
160214
let res = *asm[asm[mref].sig()].output();
161215
let addr = asm.alloc_node(CILNode::LdLocA(0));
162216
let arg0 = asm.alloc_node(CILNode::LdArg(0));
163217
let arg1 = asm.alloc_node(CILNode::LdArg(1));
164218
let ret = asm.alloc_node(CILNode::LdLoc(0));
165-
let data_ptr = FieldIdx::data_ptr(asm,res.as_class_ref().unwrap());
166-
let metadata = FieldIdx::metadata(asm,res.as_class_ref().unwrap());
219+
let data_ptr = FieldIdx::data_ptr(asm, res.as_class_ref().unwrap());
220+
let metadata = FieldIdx::metadata(asm, res.as_class_ref().unwrap());
167221
MethodImpl::MethodBody {
168-
blocks: vec![
169-
BasicBlock::new(vec![
170-
asm.alloc_root(CILRoot::SetField(Box::new((data_ptr,addr,arg0)))),
171-
asm.alloc_root(CILRoot::SetField(Box::new((metadata,addr,arg1)))),
172-
asm.alloc_root(CILRoot::Ret(ret))
173-
], 0, None),
174-
],
222+
blocks: vec![BasicBlock::new(
223+
vec![
224+
asm.alloc_root(CILRoot::SetField(Box::new((data_ptr, addr, arg0)))),
225+
asm.alloc_root(CILRoot::SetField(Box::new((metadata, addr, arg1)))),
226+
asm.alloc_root(CILRoot::Ret(ret)),
227+
],
228+
0,
229+
None,
230+
)],
175231
locals: vec![(None, asm.alloc_type(res))],
176232
}
177-
178233
};
179234
patcher.insert(name, Box::new(generator));
180235
}

cilly/src/v2/c_exporter/mod.rs

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -943,21 +943,21 @@ impl CExporter {
943943
)?;
944944
}
945945
let blocks = def.blocks(asm).unwrap().to_vec();
946-
// Prepare allocas, if needed.
947-
for root in blocks[0].roots(){
948-
let CILRoot::StLoc(loc,node ) = asm[*root] else{
949-
continue;
950-
};
951-
let CILNode::LocAllocAlgined { tpe, align } = asm[node] else {
952-
continue;
953-
};
954-
writeln!(
955-
method_defs,
956-
"register_alloca_aligned(t{hash}, {tpe},{align});",
957-
hash = encode(root.as_bimap_index().get() as u64),
958-
tpe = c_tpe(asm[tpe], asm),
959-
)?;
960-
}
946+
// Prepare allocas, if needed.
947+
for root in blocks[0].roots() {
948+
let CILRoot::StLoc(loc, node) = asm[*root] else {
949+
continue;
950+
};
951+
let CILNode::LocAllocAlgined { tpe, align } = asm[node] else {
952+
continue;
953+
};
954+
writeln!(
955+
method_defs,
956+
"register_alloca_aligned(t{hash}, {tpe},{align});",
957+
hash = encode(root.as_bimap_index().get() as u64),
958+
tpe = c_tpe(asm[tpe], asm),
959+
)?;
960+
}
961961
let mut block_iter = blocks.iter().peekable();
962962
while let Some(block) = block_iter.next() {
963963
writeln!(method_defs, "bb{}:", block.block_id())?;
@@ -1016,6 +1016,7 @@ impl CExporter {
10161016
.fields()
10171017
.iter()
10181018
.filter_map(|(tpe, _, _)| tpe.as_class_ref())
1019+
.chain(class.static_fields().iter().filter_map(|fld|fld.tpe.as_class_ref()))
10191020
.filter_map(|cref| asm.class_ref_to_def(cref))
10201021
.all(|cdef| defined_types.contains(&cdef))
10211022
{
@@ -1091,7 +1092,7 @@ impl CExporter {
10911092
} in class.static_fields()
10921093
{
10931094
let fname = escape_nonfn_name(&asm[*sfname]);
1094-
let field_tpe = c_tpe(*sfield_tpe, asm);
1095+
let field_tpe = nonvoid_c_type(*sfield_tpe, asm);
10951096
let fname = class_member_name(&class_name, &fname);
10961097
let extrn = if extrn { "extern" } else { "" };
10971098
if *is_thread_local {
@@ -1131,6 +1132,19 @@ impl CExporter {
11311132
let mut defined_types: FxHashSet<ClassDefIdx> = FxHashSet::default();
11321133
let mut delayed_defs: FxHashSet<ClassDefIdx> = asm.iter_class_def_ids().cloned().collect();
11331134
let mut delayed_defs_copy: FxHashSet<ClassDefIdx> = FxHashSet::default();
1135+
// Ensure RustVoid present
1136+
let rust_void = asm.rust_void();
1137+
self.export_class(
1138+
&mut asm,
1139+
rust_void,
1140+
&mut method_decls,
1141+
&mut method_defs,
1142+
&mut type_defs,
1143+
&mut defined_types,
1144+
&mut delayed_defs,
1145+
extrn,
1146+
)?;
1147+
delayed_defs.remove(&rust_void);
11341148
while !delayed_defs.is_empty() {
11351149
std::mem::swap(&mut delayed_defs, &mut delayed_defs_copy);
11361150
for class_def in &delayed_defs_copy {

cilly/src/v2/c_exporter/utilis.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ pub(super) fn mref_to_name(mref: &MethodRef, asm: &Assembly) -> String {
144144
.any(|tpe| matches!(tpe, Type::SIMDVector(_)))
145145
|| mname == "transmute"
146146
|| mname == "create_slice"
147+
|| mname == "ovf_check_tuple"
147148
|| mname == "_Unwind_Backtrace"
148149
{
149150
let mangled = escape_ident(

cilly/src/v2/field.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,22 @@ use super::{bimap::IntoBiMapIndex, ClassRefIdx, StringIdx, Type};
88
pub struct FieldIdx(BiMapIndex);
99
impl FieldIdx {
1010
pub(crate) fn data_ptr(asm: &mut super::Assembly, res: ClassRefIdx) -> FieldIdx {
11-
let name = asm.alloc_string(crate::DATA_PTR);
12-
let tpe = asm.nptr(Type::Void);
13-
asm.alloc_field(FieldDesc { owner: res, name, tpe})
11+
let name = asm.alloc_string(crate::DATA_PTR);
12+
let tpe = asm.nptr(Type::Void);
13+
asm.alloc_field(FieldDesc {
14+
owner: res,
15+
name,
16+
tpe,
17+
})
1418
}
15-
19+
1620
pub(crate) fn metadata(asm: &mut super::Assembly, res: ClassRefIdx) -> FieldIdx {
1721
let name = asm.alloc_string(crate::METADATA);
18-
asm.alloc_field(FieldDesc { owner: res, name, tpe:Type::Int(Int::USize)})
22+
asm.alloc_field(FieldDesc {
23+
owner: res,
24+
name,
25+
tpe: Type::Int(Int::USize),
26+
})
1927
}
2028
}
2129
impl IntoBiMapIndex for FieldIdx {

cilly/src/v2/il_exporter/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -703,14 +703,14 @@ impl ILExporter {
703703
let sfld = asm.get_static_field(sfld);
704704
let owner = class_ref(sfld.owner(), asm);
705705
let name = &asm[sfld.name()];
706-
let tpe = type_il(&sfld.tpe(), asm);
706+
let tpe = non_void_type_il(&sfld.tpe(), asm);
707707
writeln!(out, "ldsfld {tpe} {owner}::{name}")
708708
}
709709
CILNode::LdStaticFieldAdress(sfld) => {
710710
let sfld = asm.get_static_field(sfld);
711711
let owner = class_ref(sfld.owner(), asm);
712712
let name = &asm[sfld.name()];
713-
let tpe = type_il(&sfld.tpe(), asm);
713+
let tpe = non_void_type_il(&sfld.tpe(), asm);
714714
writeln!(out, "ldsflda {tpe} {owner}::{name}")
715715
}
716716
CILNode::LdFtn(ftn) => {

0 commit comments

Comments
 (0)