From be4731cd278bcdadf98febed079aec7dd98a9875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kostrubiec?= Date: Sat, 20 Jan 2024 19:38:53 +0100 Subject: [PATCH] Fix to one-variant enums. --- src/aggregate.rs | 9 +- src/binop.rs | 10 +- src/compile_test.rs | 271 ++++++++++++++++--------------- src/constant.rs | 18 +- src/rvalue.rs | 9 +- src/terminator/intrinsics/mod.rs | 61 ++++--- src/terminator/mod.rs | 3 +- src/type/tycache.rs | 109 +++++++++---- src/unop.rs | 8 +- src/utilis/adt.rs | 110 +++++++------ src/utilis/mod.rs | 2 +- 11 files changed, 349 insertions(+), 261 deletions(-) diff --git a/src/aggregate.rs b/src/aggregate.rs index cc569546..ce2dc098 100644 --- a/src/aggregate.rs +++ b/src/aggregate.rs @@ -306,8 +306,13 @@ fn aggregate_adt<'tyctx>( ops.extend(adt_adress_ops); ops.push(CILOp::LdcI32(variant_idx as i32)); let field_name = "_tag".into(); - let layout = tyctx.layout_of(rustc_middle::ty::ParamEnvAnd{param_env:ParamEnv::reveal_all(),value:adt_type}).expect("Could not get type layout!"); - let (disrc_type,_) = crate::utilis::adt::enum_tag_info(&layout.layout,tyctx); + let layout = tyctx + .layout_of(rustc_middle::ty::ParamEnvAnd { + param_env: ParamEnv::reveal_all(), + value: adt_type, + }) + .expect("Could not get type layout!"); + let (disrc_type, _) = crate::utilis::adt::enum_tag_info(&layout.layout, tyctx); ops.push(CILOp::STField(Box::new(FieldDescriptor::new( adt_type_ref, disrc_type, diff --git a/src/binop.rs b/src/binop.rs index e004af2c..62098f14 100644 --- a/src/binop.rs +++ b/src/binop.rs @@ -222,7 +222,7 @@ fn sub_unchecked<'tyctx>( } } fn ne_unchecked<'tyctx>(ty_a: Ty<'tyctx>, ty_b: Ty<'tyctx>) -> Vec { - vec![eq_unchecked(ty_a,ty_b), CILOp::LdcI32(0), CILOp::Eq] + vec![eq_unchecked(ty_a, ty_b), CILOp::LdcI32(0), CILOp::Eq] } fn eq_unchecked<'tyctx>(ty_a: Ty<'tyctx>, _ty_b: Ty<'tyctx>) -> CILOp { //vec![CILOp::Eq] @@ -237,8 +237,8 @@ fn eq_unchecked<'tyctx>(ty_a: Ty<'tyctx>, _ty_b: Ty<'tyctx>) -> CILOp { ) .into(), ), - _=>CILOp::Eq, - } + _ => CILOp::Eq, + }, TyKind::Int(int) => match int { IntTy::I128 => CILOp::Call( CallSite::new( @@ -249,8 +249,8 @@ fn eq_unchecked<'tyctx>(ty_a: Ty<'tyctx>, _ty_b: Ty<'tyctx>) -> CILOp { ) .into(), ), - _=>CILOp::Eq, - } + _ => CILOp::Eq, + }, TyKind::Bool => CILOp::Eq, TyKind::Float(_) => CILOp::Eq, TyKind::RawPtr(_) => CILOp::Eq, diff --git a/src/compile_test.rs b/src/compile_test.rs index 02dba203..f659633a 100644 --- a/src/compile_test.rs +++ b/src/compile_test.rs @@ -109,150 +109,163 @@ fn test_lib(args: &[&str], test_name: &str) { } macro_rules! test_lib { ($test_name:ident,$is_stable:ident) => { - mod $test_name {mod $is_stable{ - #[cfg(test)] - static COMPILE_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(()); - #[test] - fn release() { - // Ensures no two compilations run at the same time. - let lock = COMPILE_LOCK.lock(); - super::super::test_lib( - &[ - "-O", - "--crate-type=lib", - "-Z", - super::super::backend_path(), - "-C", - &format!("linker={}", super::super::RUSTC_CODEGEN_CLR_LINKER.display()), - concat!("../", stringify!($test_name), ".rs"), - "-o", - concat!("./", stringify!($test_name), ".rlib"), - //"--target", - // "clr64-unknown-clr" - ], - stringify!($test_name), - ); - drop(lock); - } - #[test] - fn debug() { - let lock = COMPILE_LOCK.lock(); - super::super::test_lib( - &[ - "--crate-type=lib", - "-Z", - super::super::backend_path(), - "-C", - &format!("linker={}", super::super::RUSTC_CODEGEN_CLR_LINKER.display()), - concat!("../", stringify!($test_name), ".rs"), - "-o", - concat!("./", stringify!($test_name), ".rlib"), - //"--target", - // "clr64-unknown-clr" - ], - stringify!($test_name), - ); - drop(lock); + mod $test_name { + mod $is_stable { + #[cfg(test)] + static COMPILE_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(()); + #[test] + fn release() { + // Ensures no two compilations run at the same time. + let lock = COMPILE_LOCK.lock(); + super::super::test_lib( + &[ + "-O", + "--crate-type=lib", + "-Z", + super::super::backend_path(), + "-C", + &format!( + "linker={}", + super::super::RUSTC_CODEGEN_CLR_LINKER.display() + ), + concat!("../", stringify!($test_name), ".rs"), + "-o", + concat!("./", stringify!($test_name), ".rlib"), + //"--target", + // "clr64-unknown-clr" + ], + stringify!($test_name), + ); + drop(lock); + } + #[test] + fn debug() { + let lock = COMPILE_LOCK.lock(); + super::super::test_lib( + &[ + "--crate-type=lib", + "-Z", + super::super::backend_path(), + "-C", + &format!( + "linker={}", + super::super::RUSTC_CODEGEN_CLR_LINKER.display() + ), + concat!("../", stringify!($test_name), ".rs"), + "-o", + concat!("./", stringify!($test_name), ".rlib"), + //"--target", + // "clr64-unknown-clr" + ], + stringify!($test_name), + ); + drop(lock); + } } - }} + } }; } macro_rules! run_test { ($prefix:ident,$test_name:ident,$is_stable:ident) => { - mod $test_name { mod $is_stable{ - #[cfg(test)] - use ntest::timeout; - #[cfg(test)] - static COMPILE_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(()); - #[test] - #[timeout(30_000)] - fn release() { - let lock = COMPILE_LOCK.lock(); - let test_dir = concat!("./test/", stringify!($prefix), "/"); - // Ensures the test directory is present - std::fs::create_dir_all(test_dir).expect("Could not setup the test env"); - // Builds the backend if neceasry - super::super::RUSTC_BUILD_STATUS - .as_ref() - .expect("Could not build rustc!"); - // Compiles the test project - let mut cmd = std::process::Command::new("rustc"); - //.env("RUST_TARGET_PATH","../../") - cmd.current_dir(test_dir) - .args([ - "-O", - "-Z", - super::super::backend_path(), - "-C", - &format!("linker={}", super::super::RUSTC_CODEGEN_CLR_LINKER.display()), - concat!("./", stringify!($test_name), ".rs"), - "-o", - concat!("./", stringify!($test_name), ".exe"), - //"--target", - //"clr64-unknown-clr" - ]); - eprintln!("Command: {cmd:?}"); - let out = - cmd.output() - .expect("failed to execute process"); - // If stderr is not empty, then something went wrong, so print the stdout and stderr for debuging. - if !out.stderr.is_empty() { - let stdout = String::from_utf8(out.stdout) - .expect("rustc error contained non-UTF8 characters."); - let stderr = String::from_utf8(out.stderr) - .expect("rustc error contained non-UTF8 characters."); - panic!("stdout:\n{stdout}\nstderr:\n{stderr}"); - } - let exec_path = concat!("../", stringify!($test_name)); - drop(lock); - //super::peverify(exec_path, test_dir); - - super::super::test_dotnet_executable(exec_path, test_dir); - } - #[test] - #[timeout(30_000)] - fn debug() { - let lock = COMPILE_LOCK.lock(); - let test_dir = concat!("./test/", stringify!($prefix), "/"); - // Ensures the test directory is present - std::fs::create_dir_all(test_dir).expect("Could not setup the test env"); - // Builds the backend if neceasry - super::super::RUSTC_BUILD_STATUS - .as_ref() - .expect("Could not build rustc!"); - let test_name = concat!("debug_", stringify!($test_name)); - let output_path = format!("./{test_name}.exe"); - // Compiles the test project - let out = std::process::Command::new("rustc") + mod $test_name { + mod $is_stable { + #[cfg(test)] + use ntest::timeout; + #[cfg(test)] + static COMPILE_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(()); + #[test] + #[timeout(30_000)] + fn release() { + let lock = COMPILE_LOCK.lock(); + let test_dir = concat!("./test/", stringify!($prefix), "/"); + // Ensures the test directory is present + std::fs::create_dir_all(test_dir).expect("Could not setup the test env"); + // Builds the backend if neceasry + super::super::RUSTC_BUILD_STATUS + .as_ref() + .expect("Could not build rustc!"); + // Compiles the test project + let mut cmd = std::process::Command::new("rustc"); //.env("RUST_TARGET_PATH","../../") - .current_dir(test_dir) - .args([ + cmd.current_dir(test_dir).args([ + "-O", "-Z", super::super::backend_path(), "-C", - &format!("linker={}", super::super::RUSTC_CODEGEN_CLR_LINKER.display()), + &format!( + "linker={}", + super::super::RUSTC_CODEGEN_CLR_LINKER.display() + ), concat!("./", stringify!($test_name), ".rs"), "-o", - &output_path, + concat!("./", stringify!($test_name), ".exe"), //"--target", //"clr64-unknown-clr" - ]) - .output() - .expect("failed to execute process"); - // If stderr is not empty, then something went wrong, so print the stdout and stderr for debuging. - if !out.stderr.is_empty() { - let stdout = String::from_utf8(out.stdout) - .expect("rustc error contained non-UTF8 characters."); - let stderr = String::from_utf8(out.stderr) - .expect("rustc error contained non-UTF8 characters."); - panic!("stdout:\n{stdout}\nstderr:\n{stderr}"); + ]); + eprintln!("Command: {cmd:?}"); + let out = cmd.output().expect("failed to execute process"); + // If stderr is not empty, then something went wrong, so print the stdout and stderr for debuging. + if !out.stderr.is_empty() { + let stdout = String::from_utf8(out.stdout) + .expect("rustc error contained non-UTF8 characters."); + let stderr = String::from_utf8(out.stderr) + .expect("rustc error contained non-UTF8 characters."); + panic!("stdout:\n{stdout}\nstderr:\n{stderr}"); + } + let exec_path = concat!("../", stringify!($test_name)); + drop(lock); + //super::peverify(exec_path, test_dir); + + super::super::test_dotnet_executable(exec_path, test_dir); + } + #[test] + #[timeout(30_000)] + fn debug() { + let lock = COMPILE_LOCK.lock(); + let test_dir = concat!("./test/", stringify!($prefix), "/"); + // Ensures the test directory is present + std::fs::create_dir_all(test_dir).expect("Could not setup the test env"); + // Builds the backend if neceasry + super::super::RUSTC_BUILD_STATUS + .as_ref() + .expect("Could not build rustc!"); + let test_name = concat!("debug_", stringify!($test_name)); + let output_path = format!("./{test_name}.exe"); + // Compiles the test project + let out = std::process::Command::new("rustc") + //.env("RUST_TARGET_PATH","../../") + .current_dir(test_dir) + .args([ + "-Z", + super::super::backend_path(), + "-C", + &format!( + "linker={}", + super::super::RUSTC_CODEGEN_CLR_LINKER.display() + ), + concat!("./", stringify!($test_name), ".rs"), + "-o", + &output_path, + //"--target", + //"clr64-unknown-clr" + ]) + .output() + .expect("failed to execute process"); + // If stderr is not empty, then something went wrong, so print the stdout and stderr for debuging. + if !out.stderr.is_empty() { + let stdout = String::from_utf8(out.stdout) + .expect("rustc error contained non-UTF8 characters."); + let stderr = String::from_utf8(out.stderr) + .expect("rustc error contained non-UTF8 characters."); + panic!("stdout:\n{stdout}\nstderr:\n{stderr}"); + } + let exec_path = format!("../{test_name}"); + drop(lock); + //super::peverify(&exec_path, test_dir); + super::super::test_dotnet_executable(&exec_path, test_dir); } - let exec_path = format!("../{test_name}"); - drop(lock); - //super::peverify(&exec_path, test_dir); - super::super::test_dotnet_executable(&exec_path, test_dir); } - }} + } }; } macro_rules! cargo_test { diff --git a/src/constant.rs b/src/constant.rs index 061dfb1e..058c921f 100644 --- a/src/constant.rs +++ b/src/constant.rs @@ -120,8 +120,13 @@ fn create_const_adt_from_bytes<'ctx>( } else { panic!("Invalid enum type {enum_type:?}"); }; - let layout = tyctx.layout_of(rustc_middle::ty::ParamEnvAnd{param_env:ParamEnv::reveal_all(),value:enum_ty}).expect("Could not get type layout!"); - let (disrc_type,discr_size) = crate::utilis::adt::enum_tag_info(&layout.layout,tyctx); + let layout = tyctx + .layout_of(rustc_middle::ty::ParamEnvAnd { + param_env: ParamEnv::reveal_all(), + value: enum_ty, + }) + .expect("Could not get type layout!"); + let (disrc_type, discr_size) = crate::utilis::adt::enum_tag_info(&layout.layout, tyctx); let mut ops = vec![CILOp::NewTMPLocal(enum_type.into())]; let curr_variant = match discr_size { 0 => todo!("Can't yet handle constant enums with 0-sized tags."), @@ -710,8 +715,13 @@ fn load_const_scalar<'ctx>( } TyKind::Adt(adt_def, _subst) => match adt_def.adt_kind() { AdtKind::Enum => { - let layout = tyctx.layout_of(rustc_middle::ty::ParamEnvAnd{param_env:ParamEnv::reveal_all(),value:scalar_type}).expect("Could not get type layout!"); - let (disrc_type,_) = crate::utilis::adt::enum_tag_info(&layout.layout,tyctx); + let layout = tyctx + .layout_of(rustc_middle::ty::ParamEnvAnd { + param_env: ParamEnv::reveal_all(), + value: scalar_type, + }) + .expect("Could not get type layout!"); + let (disrc_type, _) = crate::utilis::adt::enum_tag_info(&layout.layout, tyctx); let enum_dotnet = tpe.as_dotnet().expect("Enum scalar not an ADT!"); vec![ CILOp::NewTMPLocal(tpe.into()), diff --git a/src/rvalue.rs b/src/rvalue.rs index fbe9a72b..3af6c639 100644 --- a/src/rvalue.rs +++ b/src/rvalue.rs @@ -410,8 +410,13 @@ pub fn handle_rvalue<'tcx>( //TODO: chose proper tag type based on variant count of `owner` //let discr_ty = owner_ty.discriminant_ty(tyctx); //let discr_type = tycache.type_from_cache(discr_ty, tyctx, Some(method_instance)); - let layout = tyctx.layout_of(rustc_middle::ty::ParamEnvAnd{param_env:ParamEnv::reveal_all(),value:owner_ty}).expect("Could not get type layout!"); - let (disrc_type,_) = crate::utilis::adt::enum_tag_info(&layout.layout,tyctx); + let layout = tyctx + .layout_of(rustc_middle::ty::ParamEnvAnd { + param_env: ParamEnv::reveal_all(), + value: owner_ty, + }) + .expect("Could not get type layout!"); + let (disrc_type, _) = crate::utilis::adt::enum_tag_info(&layout.layout, tyctx); let owner = if let crate::r#type::Type::DotnetType(dotnet_type) = owner { dotnet_type.as_ref().clone() } else { diff --git a/src/terminator/intrinsics/mod.rs b/src/terminator/intrinsics/mod.rs index 9c7ffc1c..98d9f21e 100644 --- a/src/terminator/intrinsics/mod.rs +++ b/src/terminator/intrinsics/mod.rs @@ -285,27 +285,34 @@ pub fn handle_intrinsic<'tyctx>( &DotnetTypeRef::type_type().into(), ); let gethash_sig = FnSig::new(&[DotnetTypeRef::type_type().into()], &Type::I32); - place_set(destination, tyctx, vec![ - CILOp::LDTypeToken(tpe.into()), - CILOp::Call(CallSite::boxed( - DotnetTypeRef::type_type().into(), - "GetTypeFromHandle".into(), - sig, - true, - )), - CILOp::CallVirt(CallSite::boxed( - DotnetTypeRef::object_type().into(), - "GetHashCode".into(), - gethash_sig, - false, - )), - CILOp::Call(CallSite::boxed( - Some(DotnetTypeRef::uint_128()), - "op_Implicit".into(), - crate::function_sig::FnSig::new(&[Type::U32], &Type::U128), - true, - )), - ], body, method_instance, type_cache) + place_set( + destination, + tyctx, + vec![ + CILOp::LDTypeToken(tpe.into()), + CILOp::Call(CallSite::boxed( + DotnetTypeRef::type_type().into(), + "GetTypeFromHandle".into(), + sig, + true, + )), + CILOp::CallVirt(CallSite::boxed( + DotnetTypeRef::object_type().into(), + "GetHashCode".into(), + gethash_sig, + false, + )), + CILOp::Call(CallSite::boxed( + Some(DotnetTypeRef::uint_128()), + "op_Implicit".into(), + crate::function_sig::FnSig::new(&[Type::U32], &Type::U128), + true, + )), + ], + body, + method_instance, + type_cache, + ) } "volatile_load" => { debug_assert_eq!( @@ -385,7 +392,7 @@ pub fn handle_intrinsic<'tyctx>( ops.push(CILOp::ConvF32(false)); place_set(destination, tyctx, ops, body, method_instance, type_cache) } - "powif32"=> { + "powif32" => { debug_assert_eq!( args.len(), 2, @@ -393,12 +400,18 @@ pub fn handle_intrinsic<'tyctx>( ); let mut ops = handle_operand(&args[0].node, tyctx, body, method_instance, type_cache); ops.push(CILOp::ConvF64(false)); - ops.extend(handle_operand(&args[1].node, tyctx, body, method_instance, type_cache)); + ops.extend(handle_operand( + &args[1].node, + tyctx, + body, + method_instance, + type_cache, + )); ops.push(CILOp::ConvF64(false)); ops.push(CILOp::Call(CallSite::boxed( Some(DotnetTypeRef::new("System.Runtime".into(), "System.Math")), "Pow".into(), - FnSig::new(&[Type::F64,Type::F64], &Type::F64), + FnSig::new(&[Type::F64, Type::F64], &Type::F64), true, ))); ops.push(CILOp::ConvF32(false)); diff --git a/src/terminator/mod.rs b/src/terminator/mod.rs index 3ad7078c..f8d56507 100644 --- a/src/terminator/mod.rs +++ b/src/terminator/mod.rs @@ -178,8 +178,7 @@ pub fn handle_terminator<'ctx>( call } } - TerminatorKind::Unreachable => - CILOp::throw_msg("Unreachable reached!").into(), + TerminatorKind::Unreachable => CILOp::throw_msg("Unreachable reached!").into(), TerminatorKind::InlineAsm { template, operands, diff --git a/src/type/tycache.rs b/src/type/tycache.rs index b9997319..d1afc4a0 100644 --- a/src/type/tycache.rs +++ b/src/type/tycache.rs @@ -44,7 +44,7 @@ impl TyCache { &mut self, name: &str, def: AdtDef<'tyctx>, - adt_ty:Ty<'tyctx>, + adt_ty: Ty<'tyctx>, subst: &'tyctx List>, tyctx: TyCtxt<'tyctx>, method: Option>, @@ -61,9 +61,9 @@ impl TyCache { } self.cycle_prevention.push(name.into()); let def = match def.adt_kind() { - AdtKind::Struct => self.struct_(name, def,adt_ty, subst, tyctx, method), - AdtKind::Enum => self.enum_(name, def,adt_ty, subst, tyctx, method), - AdtKind::Union => self.union_(name, def, adt_ty,subst, tyctx, method), + AdtKind::Struct => self.struct_(name, def, adt_ty, subst, tyctx, method), + AdtKind::Enum => self.enum_(name, def, adt_ty, subst, tyctx, method), + AdtKind::Union => self.union_(name, def, adt_ty, subst, tyctx, method), }; self.type_def_cache.insert(name.into(), def); self.cycle_prevention.pop(); @@ -96,9 +96,24 @@ impl TyCache { } let access = AccessModifer::Public; - let layout = tyctx.layout_of(rustc_middle::ty::ParamEnvAnd{param_env:ParamEnv::reveal_all(),value:adt_ty}).expect("Could not get type layout!"); - let explicit_offsets = crate::utilis::adt::FieldOffsetIterator::fields(&layout.layout).collect(); - TypeDef::new(access, name.into(), vec![], fields, vec![], Some(explicit_offsets), 0, None) + let layout = tyctx + .layout_of(rustc_middle::ty::ParamEnvAnd { + param_env: ParamEnv::reveal_all(), + value: adt_ty, + }) + .expect("Could not get type layout!"); + let explicit_offsets = + crate::utilis::adt::FieldOffsetIterator::fields(&layout.layout).collect(); + TypeDef::new( + access, + name.into(), + vec![], + fields, + vec![], + Some(explicit_offsets), + 0, + None, + ) } fn union_<'tyctx>( &mut self, @@ -121,8 +136,14 @@ impl TyCache { } let access = AccessModifer::Public; - let layout = tyctx.layout_of(rustc_middle::ty::ParamEnvAnd{param_env:ParamEnv::reveal_all(),value:adt_ty}).expect("Could not get type layout!"); - let explicit_offsets = crate::utilis::adt::FieldOffsetIterator::fields(&layout.layout).collect(); + let layout = tyctx + .layout_of(rustc_middle::ty::ParamEnvAnd { + param_env: ParamEnv::reveal_all(), + value: adt_ty, + }) + .expect("Could not get type layout!"); + let explicit_offsets = + crate::utilis::adt::FieldOffsetIterator::fields(&layout.layout).collect(); TypeDef::new( access, @@ -139,54 +160,72 @@ impl TyCache { &mut self, enum_name: &str, adt: AdtDef<'tyctx>, - adt_ty:Ty<'tyctx>, + adt_ty: Ty<'tyctx>, subst: &'tyctx List>, tyctx: TyCtxt<'tyctx>, method: Option>, ) -> TypeDef { let access = AccessModifer::Public; let mut explicit_offsets: Vec = vec![]; - - let layout = tyctx.layout_of(rustc_middle::ty::ParamEnvAnd{param_env:ParamEnv::reveal_all(),value:adt_ty}).expect("Could not get type layout!"); + + let layout = tyctx + .layout_of(rustc_middle::ty::ParamEnvAnd { + param_env: ParamEnv::reveal_all(), + value: adt_ty, + }) + .expect("Could not get type layout!"); let mut fields = vec![]; let mut variant_offset = 0; let mut tag_size = 1; match &layout.variants { - rustc_target::abi::Variants::Single { index }=> todo!("Single variant enum???"), - rustc_target::abi::Variants::Multiple { tag, tag_encoding, tag_field, variants }=>{ - + rustc_target::abi::Variants::Single { index } => { + let (tag_type, offset) = crate::utilis::adt::enum_tag_info(&layout.layout, tyctx); + variant_offset = offset; + fields.push(("_tag".into(), tag_type)); + explicit_offsets.push(0); + } + rustc_target::abi::Variants::Multiple { + tag, + tag_encoding, + tag_field, + variants, + } => { let field = adt.all_fields().nth(*tag_field); - //panic!("Field:{field:?}"); - let layout = tyctx.layout_of(rustc_middle::ty::ParamEnvAnd{param_env:ParamEnv::reveal_all(),value:adt_ty}).expect("Could not get type layout!"); + //panic!("Field:{field:?}"); + let layout = tyctx + .layout_of(rustc_middle::ty::ParamEnvAnd { + param_env: ParamEnv::reveal_all(), + value: adt_ty, + }) + .expect("Could not get type layout!"); //let explicit_offsets:Vec<_> = crate::utilis::adt::FieldOffsetIterator::fields(&layout.layout).collect(); //eprintln!("explicit_offsets:{explicit_offsets:?}"); //let tag_ty = adt.all_fields().nth(0).unwrap().ty(tyctx,subst); //adt_ty.discriminant_ty(tyctx); // self.type_from_cache(tag_ty, tyctx, method); //assert_eq!(*tag_encoding,rustc_target::abi::TagEncoding::Direct,"Only direct tags supported as of now"); - match tag_encoding{ - rustc_target::abi::TagEncoding::Direct=>{ - let (tag_type,offset) = crate::utilis::adt::enum_tag_info(&layout.layout,tyctx); + match tag_encoding { + rustc_target::abi::TagEncoding::Direct => { + let (tag_type, offset) = + crate::utilis::adt::enum_tag_info(&layout.layout, tyctx); variant_offset = offset; - fields.push(( - "_tag".into(), - tag_type, - )); + fields.push(("_tag".into(), tag_type)); explicit_offsets.push(0); - }, - rustc_target::abi::TagEncoding::Niche{untagged_variant, niche_variants, niche_start}=>{ - let (tag_type,offset) = crate::utilis::adt::enum_tag_info(&layout.layout,tyctx); + } + rustc_target::abi::TagEncoding::Niche { + untagged_variant, + niche_variants, + niche_start, + } => { + let (tag_type, offset) = + crate::utilis::adt::enum_tag_info(&layout.layout, tyctx); variant_offset = offset; - fields.push(( - "_tag".into(), - tag_type, - )); + fields.push(("_tag".into(), tag_type)); explicit_offsets.push(*niche_start as u32); - }, + } } - + //todo!("Mult-variant enum!"), } - } explicit_offsets.extend(adt.variants().iter().map(|_| variant_offset)); //let mut inner_types = vec![]; @@ -327,7 +366,7 @@ impl TyCache { if super::is_name_magic(name.as_ref()) { return super::magic_type(name.as_ref(), def, subst, tyctx); } - self.adt(&name, *def, ty,subst, tyctx, method).into() + self.adt(&name, *def, ty, subst, tyctx, method).into() } TyKind::Ref(_region, inner, _mut) => { diff --git a/src/unop.rs b/src/unop.rs index 7fc8cbca..908fd33f 100644 --- a/src/unop.rs +++ b/src/unop.rs @@ -1,6 +1,6 @@ use crate::r#type::tycache::TyCache; use rustc_middle::mir::{Operand, UnOp}; -use rustc_middle::ty::{Instance, TyCtxt,TyKind}; +use rustc_middle::ty::{Instance, TyCtxt, TyKind}; use crate::cil::CILOp; pub fn unop<'ctx>( @@ -16,9 +16,9 @@ pub fn unop<'ctx>( match unnop { UnOp::Neg => ops.push(CILOp::Neg), UnOp::Not => match ty.kind() { - TyKind::Bool =>ops.extend([CILOp::LdcI32(0), CILOp::Eq]), - _=>ops.push(CILOp::Not), - } + TyKind::Bool => ops.extend([CILOp::LdcI32(0), CILOp::Eq]), + _ => ops.push(CILOp::Not), + }, }; ops } diff --git a/src/utilis/adt.rs b/src/utilis/adt.rs index 45d25c79..15e81f82 100644 --- a/src/utilis/adt.rs +++ b/src/utilis/adt.rs @@ -1,82 +1,86 @@ -use rustc_target::abi::Layout; +use crate::r#type::Type; +use rustc_middle::ty::TyCtxt; use rustc_target::abi::FieldIdx; use rustc_target::abi::FieldsShape; -use rustc_target::abi::Variants; -use rustc_middle::ty::TyCtxt; +use rustc_target::abi::Layout; use rustc_target::abi::Size; -use crate::r#type::Type; -pub(crate) enum FieldOffsetIterator{ - Explicit{ - offsets:Box<[u32]>, - index:usize, - }, - NoOffset{ - count:u64, - } +use rustc_target::abi::Variants; +pub(crate) enum FieldOffsetIterator { + Explicit { offsets: Box<[u32]>, index: usize }, + NoOffset { count: u64 }, } -impl Iterator for FieldOffsetIterator{ +impl Iterator for FieldOffsetIterator { type Item = u32; - fn next(&mut self)->Option{ - match self{ - Self::Explicit{offsets,index}=>{ + fn next(&mut self) -> Option { + match self { + Self::Explicit { offsets, index } => { let next = offsets.get(*index); *index += 1; next.copied() } - Self::NoOffset{count}=>{ + Self::NoOffset { count } => { if *count > 0 { *count -= 1; Some(0) - } - else{ + } else { None } } } - } } -impl FieldOffsetIterator{ - pub fn fields(parent:&Layout)->FieldOffsetIterator{ - match parent.fields(){ - FieldsShape::Arbitrary{offsets,memory_index}=>{ - let offsets:Box<[_]> = memory_index.iter().map(|index|offsets[FieldIdx::from_u32(*index)].bytes() as u32).collect(); - FieldOffsetIterator::Explicit{offsets,index:0} +impl FieldOffsetIterator { + pub fn fields(parent: &Layout) -> FieldOffsetIterator { + match parent.fields() { + FieldsShape::Arbitrary { + offsets, + memory_index, + } => { + let offsets: Box<[_]> = memory_index + .iter() + .map(|index| offsets[FieldIdx::from_u32(*index)].bytes() as u32) + .collect(); + FieldOffsetIterator::Explicit { offsets, index: 0 } + } + FieldsShape::Union(count) => FieldOffsetIterator::NoOffset { + count: Into::::into(*count) as u64, }, - FieldsShape::Union(count)=>FieldOffsetIterator::NoOffset{count:Into::::into(*count) as u64}, - _=>todo!() + _ => todo!(), } } } /// Takes layout of an enum as input, and returns the type of its tag(Void if no tag) and the size of the tag(0 if no tag). -pub fn enum_tag_info<'tyctx>(r#enum:&Layout<'tyctx>,tyctx:TyCtxt<'tyctx>)->(Type,u32){ - match r#enum.variants(){ - Variants::Single{..}=>(Type::Void,0), - Variants::Multiple{tag,..}=>(scalr_to_type(*tag),tag.size(&tyctx).bytes() as u32), +pub fn enum_tag_info<'tyctx>(r#enum: &Layout<'tyctx>, tyctx: TyCtxt<'tyctx>) -> (Type, u32) { + match r#enum.variants() { + Variants::Single { .. } => (Type::Void, 0), + Variants::Multiple { tag, .. } => (scalr_to_type(*tag), tag.size(&tyctx).bytes() as u32), } } -fn scalr_to_type(scalar:rustc_target::abi::Scalar)->Type{ - let primitive = match scalar {rustc_target::abi::Scalar::Union{value}=>value,rustc_target::abi::Scalar::Initialized{value,..}=>value}; +fn scalr_to_type(scalar: rustc_target::abi::Scalar) -> Type { + let primitive = match scalar { + rustc_target::abi::Scalar::Union { value } => value, + rustc_target::abi::Scalar::Initialized { value, .. } => value, + }; primitive_to_type(primitive) } -fn primitive_to_type(primitive:rustc_target::abi::Primitive)->Type{ +fn primitive_to_type(primitive: rustc_target::abi::Primitive) -> Type { + use rustc_target::abi::Integer; use rustc_target::abi::Primitive; - use rustc_target::abi::Integer; - match primitive{ - Primitive::Int(int,sign)=>match (int,sign){ - (Integer::I8,true)=>Type::I8, - (Integer::I16,true)=>Type::I16, - (Integer::I32,true)=>Type::I32, - (Integer::I64,true)=>Type::I64, - (Integer::I128,true)=>Type::I128, - (Integer::I8,false)=>Type::U8, - (Integer::I16,false)=>Type::U16, - (Integer::I32,false)=>Type::U32, - (Integer::I64,false)=>Type::U64, - (Integer::I128,false)=>Type::U128, - } - Primitive::F32=>Type::F32, - Primitive::F64=>Type::F64, - Primitive::Pointer(_)=>Type::Ptr(Type::Void.into()), + match primitive { + Primitive::Int(int, sign) => match (int, sign) { + (Integer::I8, true) => Type::I8, + (Integer::I16, true) => Type::I16, + (Integer::I32, true) => Type::I32, + (Integer::I64, true) => Type::I64, + (Integer::I128, true) => Type::I128, + (Integer::I8, false) => Type::U8, + (Integer::I16, false) => Type::U16, + (Integer::I32, false) => Type::U32, + (Integer::I64, false) => Type::U64, + (Integer::I128, false) => Type::U128, + }, + Primitive::F32 => Type::F32, + Primitive::F64 => Type::F64, + Primitive::Pointer(_) => Type::Ptr(Type::Void.into()), } -} \ No newline at end of file +} diff --git a/src/utilis/mod.rs b/src/utilis/mod.rs index 28556ef9..c9dd5c28 100644 --- a/src/utilis/mod.rs +++ b/src/utilis/mod.rs @@ -211,7 +211,7 @@ pub fn field_descrptor<'tyctx>( /// Returns the size of a tag of an enum with `variants` variants. pub fn enum_tag_size(_variants: u64) -> u32 { /*u32::try_from(((u64::from(u64::BITS) - u64::from((variants).leading_zeros())) + 8 - 1) / 8) - .expect("Enum variant over 2^4294967296")*/ + .expect("Enum variant over 2^4294967296")*/ // Seems to be always 4 1 }