Skip to content

Commit 7e0b2b5

Browse files
committed
Closure fixes
1 parent 71f409c commit 7e0b2b5

File tree

11 files changed

+187
-77
lines changed

11 files changed

+187
-77
lines changed

src/aggregate.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use crate::{
22
cil::CallSite,
33
cil::{CILOp, FieldDescriptor},
4+
operand::handle_operand,
5+
place::{place_get, place_set},
46
r#type::{DotnetTypeRef, TyCache, Type},
57
utilis::{field_name, monomorphize},
68
};
@@ -137,6 +139,55 @@ pub fn handle_aggregate<'tyctx>(
137139
ops
138140
}
139141
}
142+
AggregateKind::Closure(def_id, args) => {
143+
let closure_ty = crate::utilis::monomorphize(
144+
&method_instance,
145+
target_location.ty(method, tyctx),
146+
tyctx,
147+
)
148+
.ty;
149+
let closure_type = tycache.type_from_cache(closure_ty, tyctx, Some(method_instance));
150+
let closure_dotnet = closure_type.as_dotnet().expect("Invalid closure type!");
151+
let mut closure_constructor = vec![CILOp::NewTMPLocal(closure_type.into())];
152+
for (index, value) in value_index.iter_enumerated() {
153+
closure_constructor.push(CILOp::LoadAddresOfTMPLocal);
154+
let field_ty =
155+
crate::utilis::monomorphize(&method_instance, value.ty(method, tyctx), tyctx);
156+
let field_ty = tycache.type_from_cache(field_ty, tyctx, Some(method_instance));
157+
closure_constructor.extend(handle_operand(
158+
value,
159+
tyctx,
160+
method,
161+
method_instance,
162+
tycache,
163+
));
164+
closure_constructor.push(CILOp::STField(
165+
FieldDescriptor::new(
166+
closure_dotnet.clone(),
167+
field_ty,
168+
format!("f_{}", index.as_u32()).into(),
169+
)
170+
.into(),
171+
))
172+
}
173+
closure_constructor.extend([CILOp::LoadTMPLocal, CILOp::FreeTMPLocal]);
174+
let mut ops = place_set(
175+
target_location,
176+
tyctx,
177+
closure_constructor,
178+
method,
179+
method_instance,
180+
tycache,
181+
);
182+
ops.extend(place_get(
183+
target_location,
184+
tyctx,
185+
method,
186+
method_instance,
187+
tycache,
188+
));
189+
ops
190+
}
140191
_ => todo!("Unsuported aggregate kind {aggregate_kind:?}"),
141192
}
142193
}

src/assembly.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ impl Assembly {
238238
}
239239
if let TyKind::FnDef(_, _) = instance.ty(tcx, ParamEnv::reveal_all()).kind() {
240240
//ALL OK.
241-
} else if let TyKind::Closure(_, _) = instance.ty(tcx, ParamEnv::reveal_all()).kind(){
241+
} else if let TyKind::Closure(_, _) = instance.ty(tcx, ParamEnv::reveal_all()).kind() {
242242
println!("CLOSURE")
243243
} else {
244244
eprintln!("fn item {instance:?} is not a function definition type. Skippping.");

src/place/adress.rs

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -226,23 +226,24 @@ pub fn place_elem_adress<'ctx>(
226226
ops
227227
}
228228
TyKind::Array(element, _length) => {
229-
let element_ty = crate::utilis::monomorphize(&method_instance, *element, tyctx);
230-
let element = type_cache.type_from_cache(element_ty, tyctx, Some(method_instance));
229+
let element_ty = crate::utilis::monomorphize(&method_instance, *element, tyctx);
230+
let element =
231+
type_cache.type_from_cache(element_ty, tyctx, Some(method_instance));
231232
let array_type =
232233
type_cache.type_from_cache(curr_ty, tyctx, Some(method_instance));
233234
let array_dotnet = array_type.as_dotnet().expect("Non array type");
234235
vec![
235-
index,
236-
CILOp::Call(
237-
crate::cil::CallSite::new(
238-
Some(array_dotnet),
239-
"get_Adress".into(),
240-
FnSig::new(&[array_type, Type::USize], &element),
241-
false,
242-
)
243-
.into(),
244-
),
245-
]
236+
index,
237+
CILOp::Call(
238+
crate::cil::CallSite::new(
239+
Some(array_dotnet),
240+
"get_Adress".into(),
241+
FnSig::new(&[array_type, Type::USize], &element),
242+
false,
243+
)
244+
.into(),
245+
),
246+
]
246247
}
247248
_ => {
248249
rustc_middle::ty::print::with_no_trimmed_paths! { todo!("Can't index into {curr_ty}!")}

src/place/body.rs

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -240,28 +240,31 @@ pub fn place_elem_body<'ctx>(
240240
(inner.into(), ops)
241241
}
242242
TyKind::Array(element, _length) => {
243-
let element_ty = crate::utilis::monomorphize(&method_instance, *element, tyctx);
244-
let element = type_cache.type_from_cache(element_ty, tyctx, Some(method_instance));
243+
let element_ty = crate::utilis::monomorphize(&method_instance, *element, tyctx);
244+
let element =
245+
type_cache.type_from_cache(element_ty, tyctx, Some(method_instance));
245246
let array_type =
246247
type_cache.type_from_cache(curr_ty, tyctx, Some(method_instance));
247248
let array_dotnet = array_type.as_dotnet().expect("Non array type");
248249
if !body_ty_is_by_adress(element_ty) {
249-
((element_ty).into(),vec![
250-
index,
251-
CILOp::Call(
252-
crate::cil::CallSite::new(
253-
Some(array_dotnet),
254-
"get_Item".into(),
255-
FnSig::new(&[array_type, Type::USize], &element),
256-
false,
257-
)
258-
.into(),
259-
),
260-
])
261-
}else{
250+
(
251+
(element_ty).into(),
252+
vec![
253+
index,
254+
CILOp::Call(
255+
crate::cil::CallSite::new(
256+
Some(array_dotnet),
257+
"get_Item".into(),
258+
FnSig::new(&[array_type, Type::USize], &element),
259+
false,
260+
)
261+
.into(),
262+
),
263+
],
264+
)
265+
} else {
262266
todo!()
263267
}
264-
265268
}
266269
_ => {
267270
rustc_middle::ty::print::with_no_trimmed_paths! { todo!("Can't index into {curr_ty}!")}

src/place/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,10 @@ fn pointed_type(ty: PlaceTy) -> Ty {
3535
fn body_ty_is_by_adress(last_ty: Ty) -> bool {
3636
crate::assert_morphic!(last_ty);
3737
match *last_ty.kind() {
38-
TyKind::Adt(_, _) | TyKind::Array(_, _) => true,
38+
TyKind::Adt(_, _) | TyKind::Closure(_, _) | TyKind::Array(_, _) => true,
3939
// True for non-0 tuples
4040
TyKind::Tuple(elements) => !elements.is_empty(),
41+
4142
//TODO: check if slices are handled propely
4243
TyKind::Slice(_) | TyKind::Str => true,
4344

src/rvalue.rs

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::cil::{CILOp, FieldDescriptor, CallSite};
1+
use crate::cil::{CILOp, CallSite, FieldDescriptor};
22
use crate::function_sig::FnSig;
33
use crate::operand::handle_operand;
44
use crate::place::deref_op;
@@ -388,21 +388,39 @@ pub fn handle_rvalue<'tcx>(
388388
}
389389
ops
390390
}
391-
Rvalue::Repeat(operand,times)=>{
392-
let times = times. try_eval_target_usize(tyctx,ParamEnv::reveal_all()).expect("Could not evalute array size as usize.");
393-
let array = crate::utilis::monomorphize(&method_instance, rvalue.ty(method,tyctx), tyctx);
391+
Rvalue::Repeat(operand, times) => {
392+
let times = times
393+
.try_eval_target_usize(tyctx, ParamEnv::reveal_all())
394+
.expect("Could not evalute array size as usize.");
395+
let array =
396+
crate::utilis::monomorphize(&method_instance, rvalue.ty(method, tyctx), tyctx);
394397
let array = tycache.type_from_cache(array, tyctx, Some(method_instance));
395398
let array_dotnet = array.clone().as_dotnet().expect("Invalid array type.");
396-
397-
let operand_type = tycache.type_from_cache(crate::utilis::monomorphize(&method_instance, operand.ty(method,tyctx), tyctx), tyctx, Some(method_instance));
399+
400+
let operand_type = tycache.type_from_cache(
401+
crate::utilis::monomorphize(&method_instance, operand.ty(method, tyctx), tyctx),
402+
tyctx,
403+
Some(method_instance),
404+
);
398405
let operand = handle_operand(operand, tyctx, method, method_instance, tycache);
399406
let mut ops = Vec::new();
400407
ops.push(CILOp::NewTMPLocal(array.clone().into()));
401-
for idx in 0..times{
408+
for idx in 0..times {
402409
ops.push(CILOp::LoadAddresOfTMPLocal);
403410
ops.extend(operand.clone());
404-
ops.extend([CILOp::LdcI64(idx as u64 as i64),CILOp::ConvUSize(false)]);
405-
ops.push(CILOp::Call(CallSite::new(Some(array_dotnet.clone()),"set_Item".into(),FnSig::new(&[array.clone(),Type::USize,operand_type.clone()],&Type::Void),false).into()));
411+
ops.extend([CILOp::LdcI64(idx as u64 as i64), CILOp::ConvUSize(false)]);
412+
ops.push(CILOp::Call(
413+
CallSite::new(
414+
Some(array_dotnet.clone()),
415+
"set_Item".into(),
416+
FnSig::new(
417+
&[array.clone(), Type::USize, operand_type.clone()],
418+
&Type::Void,
419+
),
420+
false,
421+
)
422+
.into(),
423+
));
406424
}
407425
ops.push(CILOp::LoadTMPLocal);
408426
ops.push(CILOp::FreeTMPLocal);

src/terminator/call.rs

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,9 @@ pub fn call_closure<'tyctx>(
292292
type_cache: &mut crate::r#type::TyCache,
293293
) -> Vec<CILOp> {
294294
let mut call = Vec::new();
295-
let last_arg = args.get(args.len() - 1).expect("Closure must be called with at least 2 arguments(closure + arg tuple)");
295+
let last_arg = args
296+
.get(args.len() - 1)
297+
.expect("Closure must be called with at least 2 arguments(closure + arg tuple)");
296298
let other_args = &args[..args.len() - 1];
297299
for arg in other_args {
298300
call.extend(crate::operand::handle_operand(
@@ -303,34 +305,40 @@ pub fn call_closure<'tyctx>(
303305
type_cache,
304306
));
305307
}
306-
let last_arg_type = crate::utilis::monomorphize(&method_instance, last_arg.ty(body,tyctx), tyctx);
307-
match last_arg_type.kind(){
308-
TyKind::Tuple(elements)=>
309-
if elements.is_empty(){
310-
311-
}
312-
else{
308+
let last_arg_type =
309+
crate::utilis::monomorphize(&method_instance, last_arg.ty(body, tyctx), tyctx);
310+
match last_arg_type.kind() {
311+
TyKind::Tuple(elements) => {
312+
if elements.is_empty() {
313+
} else {
313314
call.extend(crate::operand::handle_operand(
314315
last_arg,
315316
tyctx,
316317
body,
317318
method_instance,
318319
type_cache,
319320
));
320-
let tuple_type = type_cache.type_from_cache(last_arg_type, tyctx, Some(method_instance));
321+
let tuple_type =
322+
type_cache.type_from_cache(last_arg_type, tyctx, Some(method_instance));
321323
call.push(CILOp::NewTMPLocal(tuple_type.clone().into()));
322324
call.push(CILOp::SetTMPLocal);
323-
for (index,element) in elements.iter().enumerate(){
325+
for (index, element) in elements.iter().enumerate() {
324326
call.push(CILOp::LoadAddresOfTMPLocal);
325-
let element_type = type_cache.type_from_cache(element, tyctx, Some(method_instance));
326-
let tuple_element_name = format!("Item{}",index + 1);
327-
let field_descriptor = FieldDescriptor::boxed(tuple_type.as_dotnet().expect("Invalid tuple type"),element_type,tuple_element_name.into());
327+
let element_type =
328+
type_cache.type_from_cache(element, tyctx, Some(method_instance));
329+
let tuple_element_name = format!("Item{}", index + 1);
330+
let field_descriptor = FieldDescriptor::boxed(
331+
tuple_type.as_dotnet().expect("Invalid tuple type"),
332+
element_type,
333+
tuple_element_name.into(),
334+
);
328335
call.push(CILOp::LDField(field_descriptor));
329336
}
330337
call.push(CILOp::FreeTMPLocal);
331338
//todo!("Can't unbox tupels yet!")
332339
}
333-
_=>panic!("Can't unbox type {last_arg_type:?}!"),
340+
}
341+
_ => panic!("Can't unbox type {last_arg_type:?}!"),
334342
}
335343
//panic!("Last arg:{last_arg:?}last_arg_type:{last_arg_type:?}");
336344
//assert_eq!(args.len(),signature.inputs().len(),"CALL SIGNATURE ARG COUNT MISMATCH!");
@@ -437,10 +445,19 @@ pub fn call<'ctx>(
437445
type_cache,
438446
);
439447
}
440-
if call_info.split_last_tuple(){
441-
return call_closure(args, destination, tyctx, signature, body, &function_name, method_instance, type_cache);
448+
if call_info.split_last_tuple() {
449+
return call_closure(
450+
args,
451+
destination,
452+
tyctx,
453+
signature,
454+
body,
455+
&function_name,
456+
method_instance,
457+
type_cache,
458+
);
442459
}
443-
460+
444461
let mut call = Vec::new();
445462
for arg in args {
446463
call.extend(crate::operand::handle_operand(

src/type/mod.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ pub fn mangle(tpe: &Type) -> std::borrow::Cow<'static, str> {
3434
);
3535
tpe.name_path().replace(".", "_").into()
3636
}
37-
Type::DotnetArray(arr)=>format!("a{}{}",arr.dimensions,mangle(&arr.element)).into(),
38-
Type::DotnetChar=>"c".into(),
39-
Type::GenericArg(_)=>todo!("Can't mangle generic type arg"),
40-
Type::FnDef(name)=>format!("fn{}{}",name.len(),name).into(),
41-
Type::Unresolved=>"un".into(),
37+
Type::DotnetArray(arr) => format!("a{}{}", arr.dimensions, mangle(&arr.element)).into(),
38+
Type::DotnetChar => "c".into(),
39+
Type::GenericArg(_) => todo!("Can't mangle generic type arg"),
40+
Type::FnDef(name) => format!("fn{}{}", name.len(), name).into(),
41+
Type::Unresolved => "un".into(),
4242
_ => todo!("Can't mangle type {tpe:?}"),
4343
}
4444
}

src/type/type_def.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,11 @@ pub fn escape_field_name(name: &str) -> IString {
172172
}
173173
}
174174
pub fn closure_name(def_id: DefId, fields: &[Type], sig: &crate::function_sig::FnSig) -> String {
175-
let mangled_fields:String = fields.iter().map(|f|crate::r#type::mangle(f)).collect();
176-
format!("Closure{field_count}{mangled_fields}",field_count = fields.len())
175+
let mangled_fields: String = fields.iter().map(|f| crate::r#type::mangle(f)).collect();
176+
format!(
177+
"Closure{field_count}{mangled_fields}",
178+
field_count = fields.len()
179+
)
177180
}
178181
pub fn closure_typedef(def_id: DefId, fields: &[Type], sig: crate::function_sig::FnSig) -> TypeDef {
179182
let name = closure_name(def_id, fields, &sig);

0 commit comments

Comments
 (0)