From b15c4123ca0fa5363e5c7668a71bd712b41b059f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kostrubiec?= Date: Wed, 31 Jan 2024 01:05:41 +0100 Subject: [PATCH 01/20] Draft version of formatting using printf(does not support enums yet, is not toglable, needs cleanup). --- mir/src/lib.rs | 1 + mir/src/serialize.rs | 13 +++- mir/src/syntax.rs | 174 ++++++++++++++++++++++++++++++++++++++++++- mir/src/tyctxt.rs | 24 +++++- 4 files changed, 206 insertions(+), 6 deletions(-) diff --git a/mir/src/lib.rs b/mir/src/lib.rs index f4025f0..fd3c73d 100644 --- a/mir/src/lib.rs +++ b/mir/src/lib.rs @@ -4,3 +4,4 @@ pub mod serialize; pub mod syntax; pub mod tyctxt; +pub const ENABLE_PRINTF_DEBUG:bool = true; \ No newline at end of file diff --git a/mir/src/serialize.rs b/mir/src/serialize.rs index d81567a..0162e41 100644 --- a/mir/src/serialize.rs +++ b/mir/src/serialize.rs @@ -316,10 +316,15 @@ impl Serialize for Body { impl Serialize for Program { fn serialize(&self, tcx: &TyCtxt) -> String { let mut program = Program::HEADER.to_string(); - if self.use_debug_dumper { - program += Program::DEBUG_DUMPER; - } else { - program += Program::DUMPER; + if crate::ENABLE_PRINTF_DEBUG{ + program += Program::PRINTF_DUMPER; + } + else{ + if self.use_debug_dumper { + program += Program::DEBUG_DUMPER; + } else { + program += Program::DUMPER; + } } program.extend(self.functions.iter_enumerated().map(|(idx, body)| { let args_list: String = body diff --git a/mir/src/syntax.rs b/mir/src/syntax.rs index decb340..5d24ad6 100644 --- a/mir/src/syntax.rs +++ b/mir/src/syntax.rs @@ -712,7 +712,7 @@ impl Program { "#[custom_mir(dialect = \"runtime\", phase = \"initial\")]"; pub const HEADER: &'static str = "#![recursion_limit = \"1024\"] #![feature(custom_mir, core_intrinsics, const_hash)] - #![allow(unused_parens, unused_assignments, overflowing_literals)] + #![allow(unused_parens, unused_assignments, overflowing_literals,internal_features)] extern crate core; use core::intrinsics::mir::*;\n"; @@ -752,7 +752,179 @@ impl Program { println!("fn{f}:_{var0} = {val0:?}\n_{var1} = {val1:?}\n_{var2} = {val2:?}\n_{var3} = {val3:?}"); } "#; + pub const PRINTF_DUMPER: &'static str = r#" + use std::ffi::{c_char, c_int}; + extern "C" { + fn printf(fmt: *const c_char, ...) -> c_int; + fn puts(str:*const c_char); + } + trait PrintFDebug{ + fn printf_debug(&self); + } + impl PrintFDebug for i8{ + fn printf_debug(&self){ + unsafe{printf("%i\0".as_ptr() as *const c_char,*self as i8 as c_int)}; + } + } + impl PrintFDebug for u8{ + fn printf_debug(&self){ + unsafe{printf("%u\0".as_ptr() as *const c_char,*self as u8 as c_int)}; + } + } + impl PrintFDebug for i16{ + fn printf_debug(&self){ + unsafe{printf("%i\0".as_ptr() as *const c_char,*self as i16 as c_int)}; + } + } + impl PrintFDebug for u16{ + fn printf_debug(&self){ + unsafe{printf("%u\0".as_ptr() as *const c_char,*self as u16 as c_int)}; + } + } + impl PrintFDebug for i32{ + fn printf_debug(&self){ + unsafe{printf("%i\0".as_ptr() as *const c_char,*self)}; + } + } + impl PrintFDebug for [T;N]{ + fn printf_debug(&self){ + unsafe{puts("[\0".as_ptr() as *const c_char)}; + for b in self{ + b.printf_debug(); + } + unsafe{puts("]\0".as_ptr() as *const c_char)}; + } + } + impl PrintFDebug for u32{ + fn printf_debug(&self){ + unsafe{printf("%u\0".as_ptr() as *const c_char,*self)}; + } + } + impl PrintFDebug for char{ + fn printf_debug(&self){ + unsafe{printf("%u\0".as_ptr() as *const c_char,*self as u64)}; + } + } + impl PrintFDebug for i64{ + fn printf_debug(&self){ + unsafe{printf("%li\0".as_ptr() as *const c_char,*self)}; + } + } + impl PrintFDebug for u64{ + fn printf_debug(&self){ + unsafe{printf("%lu\0".as_ptr() as *const c_char,*self)}; + } + } + impl PrintFDebug for i128{ + fn printf_debug(&self){ + unsafe{printf("%lu%lu\0".as_ptr() as *const c_char,*self as i64, (*self as u128 >> 64) as i64)}; + } + } + impl PrintFDebug for u128{ + fn printf_debug(&self){ + unsafe{printf("%lu%lu\0".as_ptr() as *const c_char,*self as u64, (*self >> 64) as u64)}; + } + } + impl PrintFDebug for isize{ + fn printf_debug(&self){ + unsafe{printf("%li\0".as_ptr() as *const c_char,*self as isize)}; + } + } + impl PrintFDebug for usize{ + fn printf_debug(&self){ + unsafe{printf("%lu\0".as_ptr() as *const c_char,*self as usize)}; + } + } + impl PrintFDebug for bool{ + fn printf_debug(&self){ + if *self{ + unsafe{puts("true\0".as_ptr() as *const c_char)}; + } + else{ + unsafe{puts("false\0".as_ptr() as *const c_char)}; + } + } + } + impl PrintFDebug for (){ + fn printf_debug(&self){ + unsafe{puts("()\0".as_ptr() as *const c_char)}; + } + } + impl PrintFDebug for (A,){ + fn printf_debug(&self){ + unsafe{puts("(\0".as_ptr() as *const c_char)}; + self.0.printf_debug(); + unsafe{puts(",)\0".as_ptr() as *const c_char)}; + } + } + impl PrintFDebug for (A,B){ + fn printf_debug(&self){ + unsafe{puts("(\0".as_ptr() as *const c_char)}; + self.0.printf_debug(); + unsafe{puts(",\0".as_ptr() as *const c_char)}; + self.1.printf_debug(); + unsafe{puts(")\0".as_ptr() as *const c_char)}; + } + } + impl PrintFDebug for (A,B,C){ + fn printf_debug(&self){ + unsafe{puts("(\0".as_ptr() as *const c_char)}; + self.0.printf_debug(); + unsafe{puts(",\0".as_ptr() as *const c_char)}; + self.1.printf_debug(); + unsafe{puts(",\0".as_ptr() as *const c_char)}; + self.2.printf_debug(); + unsafe{puts(")\0".as_ptr() as *const c_char)}; + } + } + impl PrintFDebug for (A,B,C,D){ + fn printf_debug(&self){ + unsafe{puts("(\0".as_ptr() as *const c_char)}; + self.0.printf_debug(); + unsafe{puts(",\0".as_ptr() as *const c_char)}; + self.1.printf_debug(); + unsafe{puts(",\0".as_ptr() as *const c_char)}; + self.2.printf_debug(); + unsafe{puts(",\0".as_ptr() as *const c_char)}; + self.3.printf_debug(); + unsafe{puts(")\0".as_ptr() as *const c_char)}; + } + } + impl PrintFDebug for (A,B,C,D,E){ + fn printf_debug(&self){ + unsafe{puts("(\0".as_ptr() as *const c_char)}; + self.0.printf_debug(); + unsafe{puts(",\0".as_ptr() as *const c_char)}; + self.1.printf_debug(); + unsafe{puts(",\0".as_ptr() as *const c_char)}; + self.2.printf_debug(); + unsafe{puts(",\0".as_ptr() as *const c_char)}; + self.3.printf_debug(); + unsafe{puts(",\0".as_ptr() as *const c_char)}; + self.4.printf_debug(); + unsafe{puts(")\0".as_ptr() as *const c_char)}; + } + } + #[inline(never)] + fn dump_var( + f: usize, + var0: usize, val0: impl PrintFDebug, + var1: usize, val1: impl PrintFDebug, + var2: usize, val2: impl PrintFDebug, + var3: usize, val3: impl PrintFDebug, + ) { + unsafe{printf("fn%u:_%u = \0".as_ptr() as *const c_char,f,var0)}; + val0.printf_debug(); + unsafe{printf("\n_%u = \0".as_ptr() as *const c_char,var1)}; + val1.printf_debug(); + unsafe{printf("\n_%u = \0".as_ptr() as *const c_char,f,var2)}; + val2.printf_debug(); + unsafe{printf("\n_%u = \0".as_ptr() as *const c_char,var3)}; + val3.printf_debug(); + unsafe{printf("\n\0".as_ptr() as *const c_char,var3)}; + } + "#; // Fake "intrinsic" pub const DUMPER_CALL: Callee = Callee::Named("dump_var"); pub const DUMPER_ARITY: usize = 4; diff --git a/mir/src/tyctxt.rs b/mir/src/tyctxt.rs index 479ce9a..b31b7d5 100644 --- a/mir/src/tyctxt.rs +++ b/mir/src/tyctxt.rs @@ -121,7 +121,12 @@ impl TyCtxt { let TyKind::Adt(adt) = adt else { panic!("not an adt"); }; - str += &self.adt_meta[&id].derive_attrs(); + if !crate::ENABLE_PRINTF_DEBUG{ + str += &self.adt_meta[&id].derive_attrs(); + } + else{ + str += &adt_impl_printf_debug(adt,id,self); + } if adt.is_enum() { let variants: String = adt .variants @@ -144,3 +149,20 @@ impl TyCtxt { str } } +pub fn adt_impl_printf_debug(adt:&Adt,id:TyId,ctx:&TyCtxt)->String{ + if adt.is_enum() { + //TODO: support enum formating! + let res = format!("impl PrintFDebug for {name}{{\n\tfn printf_debug(&self){{}}}}",name = id.type_name()); + res + } + else{ + let mut res = format!("impl PrintFDebug for {name}{{\n\tfn printf_debug(&self){{\n\tunsafe{{puts(\"{name}{{\0\".as_ptr() as *const c_char)}};",name = id.type_name()); + for (field_id,_) in adt.variants[0].fields.iter().enumerate(){ + format!("\n\tputs(\"fld{field_id}:\0\".as_ptr() as *const c_char);\n\tself.fld{field_id}.printf_debug();"); + } + res.push_str("\n\tunsafe{puts(\"}\".as_ptr() as *const c_char)};}\n}"); + res + } + +} + From cd79ada8db917007d1db728add24f177c0817c87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kostrubiec?= Date: Wed, 31 Jan 2024 21:35:37 +0100 Subject: [PATCH 02/20] Printf dumper is now toglable from the command line, and can display structs. --- generate/src/generation/mod.rs | 5 +- generate/src/main.rs | 14 ++++-- generate/src/ty.rs | 4 +- mir/src/lib.rs | 11 ++++- mir/src/serialize.rs | 19 +++----- mir/src/syntax.rs | 89 ++++++++++++++++++++++------------ mir/src/tyctxt.rs | 45 +++++++++++------ 7 files changed, 124 insertions(+), 63 deletions(-) diff --git a/generate/src/generation/mod.rs b/generate/src/generation/mod.rs index e354cdc..e6723ff 100644 --- a/generate/src/generation/mod.rs +++ b/generate/src/generation/mod.rs @@ -13,6 +13,7 @@ use mir::syntax::{ SwitchTargets, Terminator, TyId, TyKind, UnOp, VariantIdx, }; use mir::tyctxt::TyCtxt; +use mir::VarDumper; use rand::seq::SliceRandom; use rand::{seq::IteratorRandom, Rng, RngCore, SeedableRng}; use rand_distr::{Distribution, WeightedError, WeightedIndex}; @@ -921,7 +922,7 @@ impl GenerationCtx { for vars in dumpped.chunks(Program::DUMPER_ARITY) { let new_bb = self.add_new_bb(); - let args = if self.program.use_debug_dumper { + let args = if self.program.var_dumper == VarDumper::StdVarDumper || self.program.var_dumper == VarDumper::PrintfVarDumper{ let mut args = Vec::with_capacity(1 + Program::DUMPER_ARITY * 2); args.push(Operand::Constant( self.cursor.function.index().try_into().unwrap(), @@ -1166,7 +1167,7 @@ impl GenerationCtx { } } - pub fn new(seed: u64, debug_dump: bool) -> Self { + pub fn new(seed: u64, debug_dump: VarDumper) -> Self { let rng = RefCell::new(Box::new(rand::rngs::SmallRng::seed_from_u64(seed))); let tcx = Rc::new(seed_tys(&mut *rng.borrow_mut())); let ty_weights = TySelect::new(&tcx); diff --git a/generate/src/main.rs b/generate/src/main.rs index 3b31f06..f992aaf 100644 --- a/generate/src/main.rs +++ b/generate/src/main.rs @@ -18,7 +18,7 @@ use std::time::Instant; use clap::{arg, command, value_parser}; use log::{debug, info}; -use mir::serialize::Serialize; +use mir::{serialize::Serialize, VarDumper}; use crate::generation::GenerationCtx; @@ -27,6 +27,7 @@ fn main() { let matches = command!() .args(&[ arg!(-d --debug "generate a program where values are printed instead of hashed (slow)"), + arg!(-p --printf_debug "generate a program where values are printed using the C 'printf' function instead of hashed (slow)"), arg!( "generation seed").value_parser(value_parser!(u64)), ]) .get_matches(); @@ -35,12 +36,19 @@ fn main() { .get_one::("seed") .expect("need an integer as seed"); let debug_dump = matches.get_one::("debug").copied().unwrap_or(false); + let printf_dump = matches.get_one::("printf_debug").copied().unwrap_or(false); + let dumper = match (debug_dump,printf_dump){ + (false,false)=>VarDumper::HashDumper, + (true,false)=>VarDumper::StdVarDumper, + (false,true)=>VarDumper::PrintfVarDumper, + (true,true)=>panic!("You can only choose either the `debug` dumper or `printf_debug` dumper, but both of them have been selected."), + }; info!("Generating a program with seed {seed}"); - let genctxt = GenerationCtx::new(seed, debug_dump); + let genctxt = GenerationCtx::new(seed, dumper); let time = Instant::now(); let (program, tcx) = genctxt.generate(); println!("{}", program.serialize(&tcx)); - println!("{}", tcx.serialize()); + println!("{}", tcx.serialize(dumper)); let dur = time.elapsed(); debug!("took {}s to generate", dur.as_secs_f32()); } diff --git a/generate/src/ty.rs b/generate/src/ty.rs index 8b8777c..c531fc0 100644 --- a/generate/src/ty.rs +++ b/generate/src/ty.rs @@ -85,7 +85,9 @@ impl TySelect { .unwrap(); } trace!("Typing context with weights:\n{s}"); - trace!("{}", tcx.serialize()); + // FractalFir: serialization requires info about which dumper(printf-based one or not) is used. I pass `StdVarDumper` here to preserve + // previous behaviour. + trace!("{}", tcx.serialize(mir::VarDumper::StdVarDumper)); } WeightedIndex::new(tcx.iter_enumerated().map(|(tyid, _)| weights[&tyid])) diff --git a/mir/src/lib.rs b/mir/src/lib.rs index fd3c73d..672f7dc 100644 --- a/mir/src/lib.rs +++ b/mir/src/lib.rs @@ -4,4 +4,13 @@ pub mod serialize; pub mod syntax; pub mod tyctxt; -pub const ENABLE_PRINTF_DEBUG:bool = true; \ No newline at end of file +pub const ENABLE_PRINTF_DEBUG:bool = true; +#[derive(Clone,Copy,PartialEq, Eq)] +pub enum VarDumper{ + /// Print variable hashes + HashDumper, + /// Print variables using standard rust formatting + StdVarDumper, + /// Print variables using the c `printf` function + PrintfVarDumper, +} \ No newline at end of file diff --git a/mir/src/serialize.rs b/mir/src/serialize.rs index 0162e41..8e05d72 100644 --- a/mir/src/serialize.rs +++ b/mir/src/serialize.rs @@ -1,4 +1,4 @@ -use crate::{syntax::*, tyctxt::TyCtxt}; +use crate::{syntax::*, tyctxt::TyCtxt, VarDumper}; pub trait Serialize { fn serialize(&self, tcx: &TyCtxt) -> String; @@ -316,16 +316,11 @@ impl Serialize for Body { impl Serialize for Program { fn serialize(&self, tcx: &TyCtxt) -> String { let mut program = Program::HEADER.to_string(); - if crate::ENABLE_PRINTF_DEBUG{ - program += Program::PRINTF_DUMPER; - } - else{ - if self.use_debug_dumper { - program += Program::DEBUG_DUMPER; - } else { - program += Program::DUMPER; - } - } + program += match self.var_dumper{ + VarDumper::HashDumper=>Program::DUMPER, + VarDumper::StdVarDumper=>Program::DEBUG_DUMPER, + VarDumper::PrintfVarDumper=>Program::PRINTF_DUMPER, + }; program.extend(self.functions.iter_enumerated().map(|(idx, body)| { let args_list: String = body .args_iter() @@ -364,7 +359,7 @@ impl Serialize for Program { .expect("program has functions") .identifier(); - let hash_printer = if self.use_debug_dumper { + let hash_printer = if self.var_dumper != VarDumper::HashDumper { "" } else { r#" diff --git a/mir/src/syntax.rs b/mir/src/syntax.rs index 5d24ad6..571e2a7 100644 --- a/mir/src/syntax.rs +++ b/mir/src/syntax.rs @@ -3,13 +3,13 @@ use std::num::TryFromIntError; use index_vec::{define_index_type, IndexVec}; use smallvec::SmallVec; -use crate::tyctxt::TyCtxt; +use crate::{tyctxt::TyCtxt, VarDumper}; #[derive(Clone)] pub struct Program { pub functions: IndexVec, pub entry_args: Vec, - pub use_debug_dumper: bool, + pub var_dumper: VarDumper, } pub type LocalDecls = IndexVec; @@ -757,11 +757,30 @@ impl Program { extern "C" { fn printf(fmt: *const c_char, ...) -> c_int; - fn puts(str:*const c_char); } trait PrintFDebug{ fn printf_debug(&self); } + impl PrintFDebug for *const T{ + fn printf_debug(&self){ + unsafe{(**self).printf_debug()}; + } + } + impl PrintFDebug for *mut T{ + fn printf_debug(&self){ + unsafe{(**self).printf_debug()}; + } + } + impl PrintFDebug for &T{ + fn printf_debug(&self){ + (**self).printf_debug(); + } + } + impl PrintFDebug for &mut T{ + fn printf_debug(&self){ + (**self).printf_debug(); + } + } impl PrintFDebug for i8{ fn printf_debug(&self){ unsafe{printf("%i\0".as_ptr() as *const c_char,*self as i8 as c_int)}; @@ -787,13 +806,23 @@ impl Program { unsafe{printf("%i\0".as_ptr() as *const c_char,*self)}; } } + impl PrintFDebug for f32{ + fn printf_debug(&self){ + unsafe{printf("%f\0".as_ptr() as *const c_char,*self as core::ffi::c_double)}; + } + } + impl PrintFDebug for f64{ + fn printf_debug(&self){ + unsafe{printf("%f\0".as_ptr() as *const c_char,*self as core::ffi::c_double)}; + } + } impl PrintFDebug for [T;N]{ fn printf_debug(&self){ - unsafe{puts("[\0".as_ptr() as *const c_char)}; + unsafe{printf("[\0".as_ptr() as *const c_char)}; for b in self{ b.printf_debug(); } - unsafe{puts("]\0".as_ptr() as *const c_char)}; + unsafe{printf("]\0".as_ptr() as *const c_char)}; } } impl PrintFDebug for u32{ @@ -839,71 +868,71 @@ impl Program { impl PrintFDebug for bool{ fn printf_debug(&self){ if *self{ - unsafe{puts("true\0".as_ptr() as *const c_char)}; + unsafe{printf("true\0".as_ptr() as *const c_char)}; } else{ - unsafe{puts("false\0".as_ptr() as *const c_char)}; + unsafe{printf("false\0".as_ptr() as *const c_char)}; } } } impl PrintFDebug for (){ fn printf_debug(&self){ - unsafe{puts("()\0".as_ptr() as *const c_char)}; + unsafe{printf("()\0".as_ptr() as *const c_char)}; } } impl PrintFDebug for (A,){ fn printf_debug(&self){ - unsafe{puts("(\0".as_ptr() as *const c_char)}; + unsafe{printf("(\0".as_ptr() as *const c_char)}; self.0.printf_debug(); - unsafe{puts(",)\0".as_ptr() as *const c_char)}; + unsafe{printf(",)\0".as_ptr() as *const c_char)}; } } impl PrintFDebug for (A,B){ fn printf_debug(&self){ - unsafe{puts("(\0".as_ptr() as *const c_char)}; + unsafe{printf("(\0".as_ptr() as *const c_char)}; self.0.printf_debug(); - unsafe{puts(",\0".as_ptr() as *const c_char)}; + unsafe{printf(",\0".as_ptr() as *const c_char)}; self.1.printf_debug(); - unsafe{puts(")\0".as_ptr() as *const c_char)}; + unsafe{printf(")\0".as_ptr() as *const c_char)}; } } impl PrintFDebug for (A,B,C){ fn printf_debug(&self){ - unsafe{puts("(\0".as_ptr() as *const c_char)}; + unsafe{printf("(\0".as_ptr() as *const c_char)}; self.0.printf_debug(); - unsafe{puts(",\0".as_ptr() as *const c_char)}; + unsafe{printf(",\0".as_ptr() as *const c_char)}; self.1.printf_debug(); - unsafe{puts(",\0".as_ptr() as *const c_char)}; + unsafe{printf(",\0".as_ptr() as *const c_char)}; self.2.printf_debug(); - unsafe{puts(")\0".as_ptr() as *const c_char)}; + unsafe{printf(")\0".as_ptr() as *const c_char)}; } } impl PrintFDebug for (A,B,C,D){ fn printf_debug(&self){ - unsafe{puts("(\0".as_ptr() as *const c_char)}; + unsafe{printf("(\0".as_ptr() as *const c_char)}; self.0.printf_debug(); - unsafe{puts(",\0".as_ptr() as *const c_char)}; + unsafe{printf(",\0".as_ptr() as *const c_char)}; self.1.printf_debug(); - unsafe{puts(",\0".as_ptr() as *const c_char)}; + unsafe{printf(",\0".as_ptr() as *const c_char)}; self.2.printf_debug(); - unsafe{puts(",\0".as_ptr() as *const c_char)}; + unsafe{printf(",\0".as_ptr() as *const c_char)}; self.3.printf_debug(); - unsafe{puts(")\0".as_ptr() as *const c_char)}; + unsafe{printf(")\0".as_ptr() as *const c_char)}; } } impl PrintFDebug for (A,B,C,D,E){ fn printf_debug(&self){ - unsafe{puts("(\0".as_ptr() as *const c_char)}; + unsafe{printf("(\0".as_ptr() as *const c_char)}; self.0.printf_debug(); - unsafe{puts(",\0".as_ptr() as *const c_char)}; + unsafe{printf(",\0".as_ptr() as *const c_char)}; self.1.printf_debug(); - unsafe{puts(",\0".as_ptr() as *const c_char)}; + unsafe{printf(",\0".as_ptr() as *const c_char)}; self.2.printf_debug(); - unsafe{puts(",\0".as_ptr() as *const c_char)}; + unsafe{printf(",\0".as_ptr() as *const c_char)}; self.3.printf_debug(); - unsafe{puts(",\0".as_ptr() as *const c_char)}; + unsafe{printf(",\0".as_ptr() as *const c_char)}; self.4.printf_debug(); - unsafe{puts(")\0".as_ptr() as *const c_char)}; + unsafe{printf(")\0".as_ptr() as *const c_char)}; } } #[inline(never)] @@ -930,11 +959,11 @@ impl Program { pub const DUMPER_ARITY: usize = 4; // A new, empty function - pub fn new(debug: bool) -> Self { + pub fn new(debug: VarDumper) -> Self { Self { functions: IndexVec::default(), entry_args: vec![], - use_debug_dumper: debug, + var_dumper: debug, } } diff --git a/mir/src/tyctxt.rs b/mir/src/tyctxt.rs index b31b7d5..8e0d087 100644 --- a/mir/src/tyctxt.rs +++ b/mir/src/tyctxt.rs @@ -3,8 +3,7 @@ use std::{collections::HashMap, slice}; use index_vec::IndexVec; use crate::{ - serialize::Serialize, - syntax::{Adt, TyId, TyKind}, + serialize::Serialize, syntax::{Adt, TyId, TyKind}, VarDumper }; #[derive(Debug, Clone, Copy)] @@ -115,18 +114,16 @@ impl TyCtxt { self.tys.len() } - pub fn serialize(&self) -> String { + pub fn serialize(&self,dumper:VarDumper) -> String { let mut str = String::new(); for (id, adt) in self.tys.iter_enumerated().filter(|(_, kind)| kind.is_adt()) { let TyKind::Adt(adt) = adt else { panic!("not an adt"); }; - if !crate::ENABLE_PRINTF_DEBUG{ - str += &self.adt_meta[&id].derive_attrs(); - } - else{ - str += &adt_impl_printf_debug(adt,id,self); - } + str += &match dumper{ + VarDumper::HashDumper | VarDumper::StdVarDumper => self.adt_meta[&id].derive_attrs(), + VarDumper::PrintfVarDumper => adt_impl_printf_debug(adt,id), + }; if adt.is_enum() { let variants: String = adt .variants @@ -149,18 +146,38 @@ impl TyCtxt { str } } -pub fn adt_impl_printf_debug(adt:&Adt,id:TyId,ctx:&TyCtxt)->String{ +pub fn adt_impl_printf_debug(adt:&Adt,id:TyId)->String{ if adt.is_enum() { //TODO: support enum formating! - let res = format!("impl PrintFDebug for {name}{{\n\tfn printf_debug(&self){{}}}}",name = id.type_name()); + let name = id.type_name(); + let mut res = format!("impl PrintFDebug for {name}{{\n\tfn printf_debug(&self){{"); + res.push_str(&format!("unsafe{{printf(\"{name}::\\0\".as_ptr() as *const c_char)}};")); + res.push_str("match self{\n"); + for (variant_idx,variant) in adt.variants.iter().enumerate(){ + res.push_str(&format!("\tSelf::Variant{variant_idx}{{",)); + for (field_id,_) in variant.fields.iter().enumerate(){ + res.push_str(&format!("fld{field_id},")); + } + res.push_str("}=>{\n"); + res.push_str(&format!("unsafe{{printf(\"Variant{variant_idx}{{\".as_ptr() as *const c_char)}};\n")); + for (field_id,_) in variant.fields.iter().enumerate(){ + res.push_str(&format!("\t\tunsafe{{printf(\"fld{field_id}:\".as_ptr() as *const c_char)}};\n")); + res.push_str(&format!("\t\tfld{field_id}.printf_debug();\n")); + res.push_str("unsafe{printf(\",\".as_ptr() as *const c_char)};\n"); + } + res.push_str("},\n") + } + res.push_str("\t\t}\n"); + res.push_str("unsafe{printf(\"}\".as_ptr() as *const c_char)};\n"); + res.push_str("\t}\n}"); res } else{ - let mut res = format!("impl PrintFDebug for {name}{{\n\tfn printf_debug(&self){{\n\tunsafe{{puts(\"{name}{{\0\".as_ptr() as *const c_char)}};",name = id.type_name()); + let mut res = format!("impl PrintFDebug for {name}{{\n\tfn printf_debug(&self){{\n\tunsafe{{printf(\"{name}{{\0\".as_ptr() as *const c_char)}};",name = id.type_name()); for (field_id,_) in adt.variants[0].fields.iter().enumerate(){ - format!("\n\tputs(\"fld{field_id}:\0\".as_ptr() as *const c_char);\n\tself.fld{field_id}.printf_debug();"); + format!("\n\tprintf(\"fld{field_id}:\\0\".as_ptr() as *const c_char);\n\tself.fld{field_id}.printf_debug();"); } - res.push_str("\n\tunsafe{puts(\"}\".as_ptr() as *const c_char)};}\n}"); + res.push_str("\n\tunsafe{printf(\"}\".as_ptr() as *const c_char)};}\n}"); res } From 293bc4354232fc61f811b2cfdfe112333db26140 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kostrubiec?= Date: Wed, 31 Jan 2024 21:44:26 +0100 Subject: [PATCH 03/20] Added support for formatting larger tuples. --- mir/src/syntax.rs | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/mir/src/syntax.rs b/mir/src/syntax.rs index 571e2a7..d2b9d56 100644 --- a/mir/src/syntax.rs +++ b/mir/src/syntax.rs @@ -935,6 +935,42 @@ impl Program { unsafe{printf(")\0".as_ptr() as *const c_char)}; } } + impl PrintFDebug for (A,B,C,D,E,F){ + fn printf_debug(&self){ + unsafe{printf("(\0".as_ptr() as *const c_char)}; + self.0.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.1.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.2.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.3.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.4.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.5.printf_debug(); + unsafe{printf(")\0".as_ptr() as *const c_char)}; + } + } + impl PrintFDebug for (A,B,C,D,E,F,G){ + fn printf_debug(&self){ + unsafe{printf("(\0".as_ptr() as *const c_char)}; + self.0.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.1.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.2.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.3.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.4.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.5.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.6.printf_debug(); + unsafe{printf(")\0".as_ptr() as *const c_char)}; + } + } #[inline(never)] fn dump_var( f: usize, From 864d04bce22a3fff75c5555e7293ce47409efe97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kostrubiec?= Date: Wed, 31 Jan 2024 22:05:50 +0100 Subject: [PATCH 04/20] Cleanup, comments, small fixes for large tuples --- mir/src/syntax.rs | 22 ++++++++++++++++++++++ mir/src/tyctxt.rs | 15 ++++++++++++--- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/mir/src/syntax.rs b/mir/src/syntax.rs index d2b9d56..52348d5 100644 --- a/mir/src/syntax.rs +++ b/mir/src/syntax.rs @@ -752,6 +752,7 @@ impl Program { println!("fn{f}:_{var0} = {val0:?}\n_{var1} = {val1:?}\n_{var2} = {val2:?}\n_{var3} = {val3:?}"); } "#; + // Implements printf based debuggig for primitive types. pub const PRINTF_DUMPER: &'static str = r#" use std::ffi::{c_char, c_int}; @@ -971,6 +972,27 @@ impl Program { unsafe{printf(")\0".as_ptr() as *const c_char)}; } } + impl PrintFDebug for (A,B,C,D,E,F,G,H){ + fn printf_debug(&self){ + unsafe{printf("(\0".as_ptr() as *const c_char)}; + self.0.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.1.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.2.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.3.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.4.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.5.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.6.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.7.printf_debug(); + unsafe{printf(")\0".as_ptr() as *const c_char)}; + } + } #[inline(never)] fn dump_var( f: usize, diff --git a/mir/src/tyctxt.rs b/mir/src/tyctxt.rs index 8e0d087..cdd8a2b 100644 --- a/mir/src/tyctxt.rs +++ b/mir/src/tyctxt.rs @@ -120,6 +120,7 @@ impl TyCtxt { let TyKind::Adt(adt) = adt else { panic!("not an adt"); }; + // `Debug` derive is ommited for printf-based dumping. An implemntation of the PrintFDebug trait is emmited instead. str += &match dumper{ VarDumper::HashDumper | VarDumper::StdVarDumper => self.adt_meta[&id].derive_attrs(), VarDumper::PrintfVarDumper => adt_impl_printf_debug(adt,id), @@ -146,20 +147,25 @@ impl TyCtxt { str } } +// Implements the PrintFDebug trait for an ADT. +// This trait is used to dump variables using `printf` pub fn adt_impl_printf_debug(adt:&Adt,id:TyId)->String{ - if adt.is_enum() { - //TODO: support enum formating! + let res = if adt.is_enum() { + // Formats an enum let name = id.type_name(); let mut res = format!("impl PrintFDebug for {name}{{\n\tfn printf_debug(&self){{"); res.push_str(&format!("unsafe{{printf(\"{name}::\\0\".as_ptr() as *const c_char)}};")); res.push_str("match self{\n"); + // Iterate through variants cratete a match statement for (variant_idx,variant) in adt.variants.iter().enumerate(){ res.push_str(&format!("\tSelf::Variant{variant_idx}{{",)); + // Iterate trough fields to generate match patterns for (field_id,_) in variant.fields.iter().enumerate(){ res.push_str(&format!("fld{field_id},")); } res.push_str("}=>{\n"); res.push_str(&format!("unsafe{{printf(\"Variant{variant_idx}{{\".as_ptr() as *const c_char)}};\n")); + // Iterate trough fields to print values of fields of variant for (field_id,_) in variant.fields.iter().enumerate(){ res.push_str(&format!("\t\tunsafe{{printf(\"fld{field_id}:\".as_ptr() as *const c_char)}};\n")); res.push_str(&format!("\t\tfld{field_id}.printf_debug();\n")); @@ -173,13 +179,16 @@ pub fn adt_impl_printf_debug(adt:&Adt,id:TyId)->String{ res } else{ + // Formats a struct let mut res = format!("impl PrintFDebug for {name}{{\n\tfn printf_debug(&self){{\n\tunsafe{{printf(\"{name}{{\0\".as_ptr() as *const c_char)}};",name = id.type_name()); + // Iterate trough fields to print values of fields of stuct for (field_id,_) in adt.variants[0].fields.iter().enumerate(){ format!("\n\tprintf(\"fld{field_id}:\\0\".as_ptr() as *const c_char);\n\tself.fld{field_id}.printf_debug();"); } res.push_str("\n\tunsafe{printf(\"}\".as_ptr() as *const c_char)};}\n}"); res - } + }; + format!("{res}\n#[derive(Copy,Clone)]") } From 7119f946b45b1bb86a7b432391515910e43064c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kostrubiec?= Date: Wed, 31 Jan 2024 22:09:00 +0100 Subject: [PATCH 05/20] Added implementations of the formatting trait for even larger tuples --- mir/src/syntax.rs | 48 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/mir/src/syntax.rs b/mir/src/syntax.rs index 52348d5..c25f24c 100644 --- a/mir/src/syntax.rs +++ b/mir/src/syntax.rs @@ -993,6 +993,54 @@ impl Program { unsafe{printf(")\0".as_ptr() as *const c_char)}; } } + impl PrintFDebug for (A,B,C,D,E,F,G,H,I){ + fn printf_debug(&self){ + unsafe{printf("(\0".as_ptr() as *const c_char)}; + self.0.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.1.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.2.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.3.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.4.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.5.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.6.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.7.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.8.printf_debug(); + unsafe{printf(")\0".as_ptr() as *const c_char)}; + } + } + impl PrintFDebug for (A,B,C,D,E,F,G,H,I,J){ + fn printf_debug(&self){ + unsafe{printf("(\0".as_ptr() as *const c_char)}; + self.0.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.1.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.2.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.3.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.4.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.5.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.6.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.7.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.8.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; + self.9.printf_debug(); + unsafe{printf(")\0".as_ptr() as *const c_char)}; + } + } #[inline(never)] fn dump_var( f: usize, From 1dc3061b67712b2bfea8672bc40616df5e458f2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kostrubiec?= Date: Wed, 31 Jan 2024 22:29:04 +0100 Subject: [PATCH 06/20] Fixed a small issue with array formatting --- mir/src/syntax.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/mir/src/syntax.rs b/mir/src/syntax.rs index c25f24c..7c08428 100644 --- a/mir/src/syntax.rs +++ b/mir/src/syntax.rs @@ -822,6 +822,7 @@ impl Program { unsafe{printf("[\0".as_ptr() as *const c_char)}; for b in self{ b.printf_debug(); + unsafe{printf(",\0".as_ptr() as *const c_char)}; } unsafe{printf("]\0".as_ptr() as *const c_char)}; } From 345ce26d64dfb25127050d476fe9de4a35b30d7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kostrubiec?= Date: Wed, 31 Jan 2024 23:03:46 +0100 Subject: [PATCH 07/20] made debug_printf an unsafe function. Implemented the PrintFDebug trait for all tuples up to 12 elements --- mir/src/syntax.rs | 252 ++++++++++++++++++++++++++++------------------ 1 file changed, 156 insertions(+), 96 deletions(-) diff --git a/mir/src/syntax.rs b/mir/src/syntax.rs index 7c08428..e02b676 100644 --- a/mir/src/syntax.rs +++ b/mir/src/syntax.rs @@ -760,7 +760,7 @@ impl Program { fn printf(fmt: *const c_char, ...) -> c_int; } trait PrintFDebug{ - fn printf_debug(&self); + unsafe fn printf_debug(&self); } impl PrintFDebug for *const T{ fn printf_debug(&self){ @@ -784,262 +784,320 @@ impl Program { } impl PrintFDebug for i8{ fn printf_debug(&self){ - unsafe{printf("%i\0".as_ptr() as *const c_char,*self as i8 as c_int)}; + printf("%i\0".as_ptr() as *const c_char,*self as i8 as c_int)}; } } impl PrintFDebug for u8{ fn printf_debug(&self){ - unsafe{printf("%u\0".as_ptr() as *const c_char,*self as u8 as c_int)}; + printf("%u\0".as_ptr() as *const c_char,*self as u8 as c_int)}; } } impl PrintFDebug for i16{ fn printf_debug(&self){ - unsafe{printf("%i\0".as_ptr() as *const c_char,*self as i16 as c_int)}; + printf("%i\0".as_ptr() as *const c_char,*self as i16 as c_int)}; } } impl PrintFDebug for u16{ fn printf_debug(&self){ - unsafe{printf("%u\0".as_ptr() as *const c_char,*self as u16 as c_int)}; + printf("%u\0".as_ptr() as *const c_char,*self as u16 as c_int)}; } } impl PrintFDebug for i32{ fn printf_debug(&self){ - unsafe{printf("%i\0".as_ptr() as *const c_char,*self)}; + printf("%i\0".as_ptr() as *const c_char,*self)}; } } impl PrintFDebug for f32{ fn printf_debug(&self){ - unsafe{printf("%f\0".as_ptr() as *const c_char,*self as core::ffi::c_double)}; + printf("%f\0".as_ptr() as *const c_char,*self as core::ffi::c_double)}; } } impl PrintFDebug for f64{ fn printf_debug(&self){ - unsafe{printf("%f\0".as_ptr() as *const c_char,*self as core::ffi::c_double)}; + printf("%f\0".as_ptr() as *const c_char,*self as core::ffi::c_double)}; } } impl PrintFDebug for [T;N]{ fn printf_debug(&self){ - unsafe{printf("[\0".as_ptr() as *const c_char)}; + printf("[\0".as_ptr() as *const c_char); for b in self{ b.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); } - unsafe{printf("]\0".as_ptr() as *const c_char)}; + printf("]\0".as_ptr() as *const c_char); } } impl PrintFDebug for u32{ fn printf_debug(&self){ - unsafe{printf("%u\0".as_ptr() as *const c_char,*self)}; + printf("%u\0".as_ptr() as *const c_char,*self)}; } } impl PrintFDebug for char{ fn printf_debug(&self){ - unsafe{printf("%u\0".as_ptr() as *const c_char,*self as u64)}; + printf("%u\0".as_ptr() as *const c_char,*self as u64); } } impl PrintFDebug for i64{ fn printf_debug(&self){ - unsafe{printf("%li\0".as_ptr() as *const c_char,*self)}; + printf("%li\0".as_ptr() as *const c_char,*self); } } impl PrintFDebug for u64{ fn printf_debug(&self){ - unsafe{printf("%lu\0".as_ptr() as *const c_char,*self)}; + printf("%lu\0".as_ptr() as *const c_char,*self); } } impl PrintFDebug for i128{ fn printf_debug(&self){ - unsafe{printf("%lu%lu\0".as_ptr() as *const c_char,*self as i64, (*self as u128 >> 64) as i64)}; + printf("%lu%lu\0".as_ptr() as *const c_char,*self as i64, (*self as u128 >> 64) as i64); } } impl PrintFDebug for u128{ fn printf_debug(&self){ - unsafe{printf("%lu%lu\0".as_ptr() as *const c_char,*self as u64, (*self >> 64) as u64)}; + printf("%lu%lu\0".as_ptr() as *const c_char,*self as u64, (*self >> 64) as u64); } } impl PrintFDebug for isize{ fn printf_debug(&self){ - unsafe{printf("%li\0".as_ptr() as *const c_char,*self as isize)}; + printf("%li\0".as_ptr() as *const c_char,*self as isize); } } impl PrintFDebug for usize{ fn printf_debug(&self){ - unsafe{printf("%lu\0".as_ptr() as *const c_char,*self as usize)}; + printf("%lu\0".as_ptr() as *const c_char,*self as usize); } } impl PrintFDebug for bool{ fn printf_debug(&self){ if *self{ - unsafe{printf("true\0".as_ptr() as *const c_char)}; + printf("true\0".as_ptr() as *const c_char); } else{ - unsafe{printf("false\0".as_ptr() as *const c_char)}; + printf("false\0".as_ptr() as *const c_char); } } } impl PrintFDebug for (){ fn printf_debug(&self){ - unsafe{printf("()\0".as_ptr() as *const c_char)}; + printf("()\0".as_ptr() as *const c_char); } } impl PrintFDebug for (A,){ fn printf_debug(&self){ - unsafe{printf("(\0".as_ptr() as *const c_char)}; + printf("(\0".as_ptr() as *const c_char); self.0.printf_debug(); - unsafe{printf(",)\0".as_ptr() as *const c_char)}; + printf(",)\0".as_ptr() as *const c_char); } } impl PrintFDebug for (A,B){ fn printf_debug(&self){ - unsafe{printf("(\0".as_ptr() as *const c_char)}; + printf("(\0".as_ptr() as *const c_char); self.0.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.1.printf_debug(); - unsafe{printf(")\0".as_ptr() as *const c_char)}; + printf(")\0".as_ptr() as *const c_char); } } impl PrintFDebug for (A,B,C){ fn printf_debug(&self){ - unsafe{printf("(\0".as_ptr() as *const c_char)}; + printf("(\0".as_ptr() as *const c_char); self.0.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.1.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.2.printf_debug(); - unsafe{printf(")\0".as_ptr() as *const c_char)}; + printf(")\0".as_ptr() as *const c_char); } } impl PrintFDebug for (A,B,C,D){ fn printf_debug(&self){ - unsafe{printf("(\0".as_ptr() as *const c_char)}; + printf("(\0".as_ptr() as *const c_char); self.0.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.1.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.2.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.3.printf_debug(); - unsafe{printf(")\0".as_ptr() as *const c_char)}; + printf(")\0".as_ptr() as *const c_char); } } impl PrintFDebug for (A,B,C,D,E){ fn printf_debug(&self){ - unsafe{printf("(\0".as_ptr() as *const c_char)}; + printf("(\0".as_ptr() as *const c_char); self.0.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.1.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.2.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.3.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.4.printf_debug(); - unsafe{printf(")\0".as_ptr() as *const c_char)}; + printf(")\0".as_ptr() as *const c_char); } } impl PrintFDebug for (A,B,C,D,E,F){ fn printf_debug(&self){ - unsafe{printf("(\0".as_ptr() as *const c_char)}; + printf("(\0".as_ptr() as *const c_char); self.0.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.1.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.2.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.3.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.4.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.5.printf_debug(); - unsafe{printf(")\0".as_ptr() as *const c_char)}; + printf(")\0".as_ptr() as *const c_char); } } impl PrintFDebug for (A,B,C,D,E,F,G){ fn printf_debug(&self){ - unsafe{printf("(\0".as_ptr() as *const c_char)}; + printf("(\0".as_ptr() as *const c_char); self.0.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.1.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.2.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.3.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.4.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.5.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.6.printf_debug(); - unsafe{printf(")\0".as_ptr() as *const c_char)}; + printf(")\0".as_ptr() as *const c_char); } } impl PrintFDebug for (A,B,C,D,E,F,G,H){ fn printf_debug(&self){ - unsafe{printf("(\0".as_ptr() as *const c_char)}; + printf("(\0".as_ptr() as *const c_char); self.0.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.1.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.2.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.3.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.4.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.5.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.6.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.7.printf_debug(); - unsafe{printf(")\0".as_ptr() as *const c_char)}; + printf(")\0".as_ptr() as *const c_char); } } impl PrintFDebug for (A,B,C,D,E,F,G,H,I){ fn printf_debug(&self){ - unsafe{printf("(\0".as_ptr() as *const c_char)}; + printf("(\0".as_ptr() as *const c_char); self.0.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.1.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.2.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.3.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.4.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.5.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.6.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.7.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.8.printf_debug(); - unsafe{printf(")\0".as_ptr() as *const c_char)}; + printf(")\0".as_ptr() as *const c_char); } } impl PrintFDebug for (A,B,C,D,E,F,G,H,I,J){ fn printf_debug(&self){ - unsafe{printf("(\0".as_ptr() as *const c_char)}; + printf("(\0".as_ptr() as *const c_char); self.0.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.1.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.2.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.3.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.4.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.5.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.6.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.7.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.8.printf_debug(); - unsafe{printf(",\0".as_ptr() as *const c_char)}; + printf(",\0".as_ptr() as *const c_char); self.9.printf_debug(); - unsafe{printf(")\0".as_ptr() as *const c_char)}; + printf(")\0".as_ptr() as *const c_char); + } + } + impl PrintFDebug for (A,B,C,D,E,F,G,H,I,J,K){ + fn printf_debug(&self){ + printf("(\0".as_ptr() as *const c_char); + self.0.printf_debug(); + printf(",\0".as_ptr() as *const c_char); + self.1.printf_debug(); + printf(",\0".as_ptr() as *const c_char); + self.2.printf_debug(); + printf(",\0".as_ptr() as *const c_char); + self.3.printf_debug(); + printf(",\0".as_ptr() as *const c_char); + self.4.printf_debug(); + printf(",\0".as_ptr() as *const c_char); + self.5.printf_debug(); + printf(",\0".as_ptr() as *const c_char); + self.6.printf_debug(); + printf(",\0".as_ptr() as *const c_char); + self.7.printf_debug(); + printf(",\0".as_ptr() as *const c_char); + self.8.printf_debug(); + printf(",\0".as_ptr() as *const c_char); + self.9.printf_debug(); + printf(",\0".as_ptr() as *const c_char); + self.10.printf_debug(); + printf(")\0".as_ptr() as *const c_char); + } + } + impl PrintFDebug for (A,B,C,D,E,F,G,H,I,J,K,L){ + fn printf_debug(&self){ + printf("(\0".as_ptr() as *const c_char); + self.0.printf_debug(); + printf(",\0".as_ptr() as *const c_char); + self.1.printf_debug(); + printf(",\0".as_ptr() as *const c_char); + self.2.printf_debug(); + printf(",\0".as_ptr() as *const c_char); + self.3.printf_debug(); + printf(",\0".as_ptr() as *const c_char); + self.4.printf_debug(); + printf(",\0".as_ptr() as *const c_char); + self.5.printf_debug(); + printf(",\0".as_ptr() as *const c_char); + self.6.printf_debug(); + printf(",\0".as_ptr() as *const c_char); + self.7.printf_debug(); + printf(",\0".as_ptr() as *const c_char); + self.8.printf_debug(); + printf(",\0".as_ptr() as *const c_char); + self.9.printf_debug(); + printf(",\0".as_ptr() as *const c_char); + self.10.printf_debug(); + printf(",\0".as_ptr() as *const c_char); + self.11.printf_debug(); + printf(",\0".as_ptr() as *const c_char); + self.12.printf_debug(); + printf(")\0".as_ptr() as *const c_char); } } #[inline(never)] @@ -1050,15 +1108,17 @@ impl Program { var2: usize, val2: impl PrintFDebug, var3: usize, val3: impl PrintFDebug, ) { - unsafe{printf("fn%u:_%u = \0".as_ptr() as *const c_char,f,var0)}; - val0.printf_debug(); - unsafe{printf("\n_%u = \0".as_ptr() as *const c_char,var1)}; - val1.printf_debug(); - unsafe{printf("\n_%u = \0".as_ptr() as *const c_char,f,var2)}; - val2.printf_debug(); - unsafe{printf("\n_%u = \0".as_ptr() as *const c_char,var3)}; - val3.printf_debug(); - unsafe{printf("\n\0".as_ptr() as *const c_char,var3)}; + unsafe{ + printf("fn%u:_%u = \0".as_ptr() as *const c_char,f,var0)}; + val0.printf_debug(); + printf("\n_%u = \0".as_ptr() as *const c_char,var1)}; + val1.printf_debug(); + printf("\n_%u = \0".as_ptr() as *const c_char,f,var2)}; + val2.printf_debug(); + printf("\n_%u = \0".as_ptr() as *const c_char,var3)}; + val3.printf_debug(); + printf("\n\0".as_ptr() as *const c_char,var3)}; + } } "#; // Fake "intrinsic" From 97ce8ecf112988ac430b440a5849cd6db23fda75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kostrubiec?= Date: Mon, 5 Feb 2024 22:47:20 +0100 Subject: [PATCH 08/20] Small fix to generated printf formatting --- mir/src/syntax.rs | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/mir/src/syntax.rs b/mir/src/syntax.rs index e02b676..818c7f3 100644 --- a/mir/src/syntax.rs +++ b/mir/src/syntax.rs @@ -764,12 +764,12 @@ impl Program { } impl PrintFDebug for *const T{ fn printf_debug(&self){ - unsafe{(**self).printf_debug()}; + unsafe{(**self).printf_debug(); } } impl PrintFDebug for *mut T{ fn printf_debug(&self){ - unsafe{(**self).printf_debug()}; + unsafe{(**self).printf_debug(); } } impl PrintFDebug for &T{ @@ -784,37 +784,37 @@ impl Program { } impl PrintFDebug for i8{ fn printf_debug(&self){ - printf("%i\0".as_ptr() as *const c_char,*self as i8 as c_int)}; + printf("%i\0".as_ptr() as *const c_char,*self as i8 as c_int); } } impl PrintFDebug for u8{ fn printf_debug(&self){ - printf("%u\0".as_ptr() as *const c_char,*self as u8 as c_int)}; + printf("%u\0".as_ptr() as *const c_char,*self as u8 as c_int); } } impl PrintFDebug for i16{ fn printf_debug(&self){ - printf("%i\0".as_ptr() as *const c_char,*self as i16 as c_int)}; + printf("%i\0".as_ptr() as *const c_char,*self as i16 as c_int); } } impl PrintFDebug for u16{ fn printf_debug(&self){ - printf("%u\0".as_ptr() as *const c_char,*self as u16 as c_int)}; + printf("%u\0".as_ptr() as *const c_char,*self as u16 as c_int); } } impl PrintFDebug for i32{ fn printf_debug(&self){ - printf("%i\0".as_ptr() as *const c_char,*self)}; + printf("%i\0".as_ptr() as *const c_char,*self); } } impl PrintFDebug for f32{ fn printf_debug(&self){ - printf("%f\0".as_ptr() as *const c_char,*self as core::ffi::c_double)}; + printf("%f\0".as_ptr() as *const c_char,*self as core::ffi::c_double); } } impl PrintFDebug for f64{ fn printf_debug(&self){ - printf("%f\0".as_ptr() as *const c_char,*self as core::ffi::c_double)}; + printf("%f\0".as_ptr() as *const c_char,*self as core::ffi::c_double); } } impl PrintFDebug for [T;N]{ @@ -829,7 +829,7 @@ impl Program { } impl PrintFDebug for u32{ fn printf_debug(&self){ - printf("%u\0".as_ptr() as *const c_char,*self)}; + printf("%u\0".as_ptr() as *const c_char,*self); } } impl PrintFDebug for char{ @@ -1109,15 +1109,15 @@ impl Program { var3: usize, val3: impl PrintFDebug, ) { unsafe{ - printf("fn%u:_%u = \0".as_ptr() as *const c_char,f,var0)}; + printf("fn%u:_%u = \0".as_ptr() as *const c_char,f,var0); val0.printf_debug(); - printf("\n_%u = \0".as_ptr() as *const c_char,var1)}; + printf("\n_%u = \0".as_ptr() as *const c_char,var1); val1.printf_debug(); - printf("\n_%u = \0".as_ptr() as *const c_char,f,var2)}; + printf("\n_%u = \0".as_ptr() as *const c_char,f,var2); val2.printf_debug(); - printf("\n_%u = \0".as_ptr() as *const c_char,var3)}; + printf("\n_%u = \0".as_ptr() as *const c_char,var3); val3.printf_debug(); - printf("\n\0".as_ptr() as *const c_char,var3)}; + printf("\n\0".as_ptr() as *const c_char,var3); } } "#; From 6d60354c903021f7adb8a3f87511b48c8dc50825 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kostrubiec?= Date: Mon, 5 Feb 2024 23:13:25 +0100 Subject: [PATCH 09/20] Small fix to generated printf formatting --- mir/src/syntax.rs | 76 +++++++++++++++++++++++------------------------ mir/src/tyctxt.rs | 4 +-- 2 files changed, 39 insertions(+), 41 deletions(-) diff --git a/mir/src/syntax.rs b/mir/src/syntax.rs index 818c7f3..62e8af0 100644 --- a/mir/src/syntax.rs +++ b/mir/src/syntax.rs @@ -763,62 +763,62 @@ impl Program { unsafe fn printf_debug(&self); } impl PrintFDebug for *const T{ - fn printf_debug(&self){ - unsafe{(**self).printf_debug(); + unsafe fn printf_debug(&self){ + unsafe{(**self).printf_debug()}; } } impl PrintFDebug for *mut T{ - fn printf_debug(&self){ - unsafe{(**self).printf_debug(); + unsafe fn printf_debug(&self){ + unsafe{(**self).printf_debug()}; } } impl PrintFDebug for &T{ - fn printf_debug(&self){ + unsafe fn printf_debug(&self){ (**self).printf_debug(); } } impl PrintFDebug for &mut T{ - fn printf_debug(&self){ + unsafe fn printf_debug(&self){ (**self).printf_debug(); } } impl PrintFDebug for i8{ - fn printf_debug(&self){ + unsafe fn printf_debug(&self){ printf("%i\0".as_ptr() as *const c_char,*self as i8 as c_int); } } impl PrintFDebug for u8{ - fn printf_debug(&self){ + unsafe fn printf_debug(&self){ printf("%u\0".as_ptr() as *const c_char,*self as u8 as c_int); } } impl PrintFDebug for i16{ - fn printf_debug(&self){ + unsafe fn printf_debug(&self){ printf("%i\0".as_ptr() as *const c_char,*self as i16 as c_int); } } impl PrintFDebug for u16{ - fn printf_debug(&self){ + unsafe fn printf_debug(&self){ printf("%u\0".as_ptr() as *const c_char,*self as u16 as c_int); } } impl PrintFDebug for i32{ - fn printf_debug(&self){ + unsafe fn printf_debug(&self){ printf("%i\0".as_ptr() as *const c_char,*self); } } impl PrintFDebug for f32{ - fn printf_debug(&self){ + unsafe fn printf_debug(&self){ printf("%f\0".as_ptr() as *const c_char,*self as core::ffi::c_double); } } impl PrintFDebug for f64{ - fn printf_debug(&self){ + unsafe fn printf_debug(&self){ printf("%f\0".as_ptr() as *const c_char,*self as core::ffi::c_double); } } impl PrintFDebug for [T;N]{ - fn printf_debug(&self){ + unsafe fn printf_debug(&self){ printf("[\0".as_ptr() as *const c_char); for b in self{ b.printf_debug(); @@ -828,47 +828,47 @@ impl Program { } } impl PrintFDebug for u32{ - fn printf_debug(&self){ + unsafe fn printf_debug(&self){ printf("%u\0".as_ptr() as *const c_char,*self); } } impl PrintFDebug for char{ - fn printf_debug(&self){ + unsafe fn printf_debug(&self){ printf("%u\0".as_ptr() as *const c_char,*self as u64); } } impl PrintFDebug for i64{ - fn printf_debug(&self){ + unsafe fn printf_debug(&self){ printf("%li\0".as_ptr() as *const c_char,*self); } } impl PrintFDebug for u64{ - fn printf_debug(&self){ + unsafe fn printf_debug(&self){ printf("%lu\0".as_ptr() as *const c_char,*self); } } impl PrintFDebug for i128{ - fn printf_debug(&self){ + unsafe fn printf_debug(&self){ printf("%lu%lu\0".as_ptr() as *const c_char,*self as i64, (*self as u128 >> 64) as i64); } } impl PrintFDebug for u128{ - fn printf_debug(&self){ + unsafe fn printf_debug(&self){ printf("%lu%lu\0".as_ptr() as *const c_char,*self as u64, (*self >> 64) as u64); } } impl PrintFDebug for isize{ - fn printf_debug(&self){ + unsafe fn printf_debug(&self){ printf("%li\0".as_ptr() as *const c_char,*self as isize); } } impl PrintFDebug for usize{ - fn printf_debug(&self){ + unsafe fn printf_debug(&self){ printf("%lu\0".as_ptr() as *const c_char,*self as usize); } } impl PrintFDebug for bool{ - fn printf_debug(&self){ + unsafe fn printf_debug(&self){ if *self{ printf("true\0".as_ptr() as *const c_char); } @@ -878,19 +878,19 @@ impl Program { } } impl PrintFDebug for (){ - fn printf_debug(&self){ + unsafe fn printf_debug(&self){ printf("()\0".as_ptr() as *const c_char); } } impl PrintFDebug for (A,){ - fn printf_debug(&self){ + unsafe fn printf_debug(&self){ printf("(\0".as_ptr() as *const c_char); self.0.printf_debug(); printf(",)\0".as_ptr() as *const c_char); } } impl PrintFDebug for (A,B){ - fn printf_debug(&self){ + unsafe fn printf_debug(&self){ printf("(\0".as_ptr() as *const c_char); self.0.printf_debug(); printf(",\0".as_ptr() as *const c_char); @@ -899,7 +899,7 @@ impl Program { } } impl PrintFDebug for (A,B,C){ - fn printf_debug(&self){ + unsafe fn printf_debug(&self){ printf("(\0".as_ptr() as *const c_char); self.0.printf_debug(); printf(",\0".as_ptr() as *const c_char); @@ -910,7 +910,7 @@ impl Program { } } impl PrintFDebug for (A,B,C,D){ - fn printf_debug(&self){ + unsafe fn printf_debug(&self){ printf("(\0".as_ptr() as *const c_char); self.0.printf_debug(); printf(",\0".as_ptr() as *const c_char); @@ -923,7 +923,7 @@ impl Program { } } impl PrintFDebug for (A,B,C,D,E){ - fn printf_debug(&self){ + unsafe fn printf_debug(&self){ printf("(\0".as_ptr() as *const c_char); self.0.printf_debug(); printf(",\0".as_ptr() as *const c_char); @@ -938,7 +938,7 @@ impl Program { } } impl PrintFDebug for (A,B,C,D,E,F){ - fn printf_debug(&self){ + unsafe fn printf_debug(&self){ printf("(\0".as_ptr() as *const c_char); self.0.printf_debug(); printf(",\0".as_ptr() as *const c_char); @@ -955,7 +955,7 @@ impl Program { } } impl PrintFDebug for (A,B,C,D,E,F,G){ - fn printf_debug(&self){ + unsafe fn printf_debug(&self){ printf("(\0".as_ptr() as *const c_char); self.0.printf_debug(); printf(",\0".as_ptr() as *const c_char); @@ -974,7 +974,7 @@ impl Program { } } impl PrintFDebug for (A,B,C,D,E,F,G,H){ - fn printf_debug(&self){ + unsafe fn printf_debug(&self){ printf("(\0".as_ptr() as *const c_char); self.0.printf_debug(); printf(",\0".as_ptr() as *const c_char); @@ -995,7 +995,7 @@ impl Program { } } impl PrintFDebug for (A,B,C,D,E,F,G,H,I){ - fn printf_debug(&self){ + unsafe fn printf_debug(&self){ printf("(\0".as_ptr() as *const c_char); self.0.printf_debug(); printf(",\0".as_ptr() as *const c_char); @@ -1018,7 +1018,7 @@ impl Program { } } impl PrintFDebug for (A,B,C,D,E,F,G,H,I,J){ - fn printf_debug(&self){ + unsafe fn printf_debug(&self){ printf("(\0".as_ptr() as *const c_char); self.0.printf_debug(); printf(",\0".as_ptr() as *const c_char); @@ -1043,7 +1043,7 @@ impl Program { } } impl PrintFDebug for (A,B,C,D,E,F,G,H,I,J,K){ - fn printf_debug(&self){ + unsafe fn printf_debug(&self){ printf("(\0".as_ptr() as *const c_char); self.0.printf_debug(); printf(",\0".as_ptr() as *const c_char); @@ -1069,8 +1069,8 @@ impl Program { printf(")\0".as_ptr() as *const c_char); } } - impl PrintFDebug for (A,B,C,D,E,F,G,H,I,J,K,L){ - fn printf_debug(&self){ + impl PrintFDebug for (A,B,C,D,E,F,G,H,I,J,K,L){ + unsafe fn printf_debug(&self){ printf("(\0".as_ptr() as *const c_char); self.0.printf_debug(); printf(",\0".as_ptr() as *const c_char); @@ -1095,8 +1095,6 @@ impl Program { self.10.printf_debug(); printf(",\0".as_ptr() as *const c_char); self.11.printf_debug(); - printf(",\0".as_ptr() as *const c_char); - self.12.printf_debug(); printf(")\0".as_ptr() as *const c_char); } } diff --git a/mir/src/tyctxt.rs b/mir/src/tyctxt.rs index cdd8a2b..56cc84b 100644 --- a/mir/src/tyctxt.rs +++ b/mir/src/tyctxt.rs @@ -153,7 +153,7 @@ pub fn adt_impl_printf_debug(adt:&Adt,id:TyId)->String{ let res = if adt.is_enum() { // Formats an enum let name = id.type_name(); - let mut res = format!("impl PrintFDebug for {name}{{\n\tfn printf_debug(&self){{"); + let mut res = format!("impl PrintFDebug for {name}{{\n\tunsafe fn printf_debug(&self){{"); res.push_str(&format!("unsafe{{printf(\"{name}::\\0\".as_ptr() as *const c_char)}};")); res.push_str("match self{\n"); // Iterate through variants cratete a match statement @@ -180,7 +180,7 @@ pub fn adt_impl_printf_debug(adt:&Adt,id:TyId)->String{ } else{ // Formats a struct - let mut res = format!("impl PrintFDebug for {name}{{\n\tfn printf_debug(&self){{\n\tunsafe{{printf(\"{name}{{\0\".as_ptr() as *const c_char)}};",name = id.type_name()); + let mut res = format!("impl PrintFDebug for {name}{{\n\tunsafe fn printf_debug(&self){{\n\tunsafe{{printf(\"{name}{{\0\".as_ptr() as *const c_char)}};",name = id.type_name()); // Iterate trough fields to print values of fields of stuct for (field_id,_) in adt.variants[0].fields.iter().enumerate(){ format!("\n\tprintf(\"fld{field_id}:\\0\".as_ptr() as *const c_char);\n\tself.fld{field_id}.printf_debug();"); From 120bf6d20a524db77dbf7b318fe138a4c9b013fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kostrubiec?= Date: Mon, 12 Feb 2024 21:18:06 +0100 Subject: [PATCH 10/20] Small fix to 128 bit int formatting --- mir/src/syntax.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mir/src/syntax.rs b/mir/src/syntax.rs index 62e8af0..dba9a9c 100644 --- a/mir/src/syntax.rs +++ b/mir/src/syntax.rs @@ -849,12 +849,12 @@ impl Program { } impl PrintFDebug for i128{ unsafe fn printf_debug(&self){ - printf("%lu%lu\0".as_ptr() as *const c_char,*self as i64, (*self as u128 >> 64) as i64); + u128::printf_debug(&(*self as u128)); } } impl PrintFDebug for u128{ unsafe fn printf_debug(&self){ - printf("%lu%lu\0".as_ptr() as *const c_char,*self as u64, (*self >> 64) as u64); + printf("%lx%lx\0".as_ptr() as *const c_char, (*self >> 64) as u64,*self as u64); } } impl PrintFDebug for isize{ From 38e581b53d15a5db393224f626fce88434b5f6e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kostrubiec?= Date: Mon, 12 Feb 2024 22:54:59 +0100 Subject: [PATCH 11/20] Fixed a couple of typos --- mir/src/syntax.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mir/src/syntax.rs b/mir/src/syntax.rs index dba9a9c..40d6bd6 100644 --- a/mir/src/syntax.rs +++ b/mir/src/syntax.rs @@ -1111,11 +1111,11 @@ impl Program { val0.printf_debug(); printf("\n_%u = \0".as_ptr() as *const c_char,var1); val1.printf_debug(); - printf("\n_%u = \0".as_ptr() as *const c_char,f,var2); + printf("\n_%u = \0".as_ptr() as *const c_char,var2); val2.printf_debug(); printf("\n_%u = \0".as_ptr() as *const c_char,var3); val3.printf_debug(); - printf("\n\0".as_ptr() as *const c_char,var3); + printf("\n\0".as_ptr() as *const c_char); } } "#; From 25ec83de50b3e77323d11518af1933f2916696a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kostrubiec?= Date: Mon, 29 Apr 2024 00:20:12 +0200 Subject: [PATCH 12/20] Fixed missing null terminators in enum display --- mir/src/tyctxt.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/mir/src/tyctxt.rs b/mir/src/tyctxt.rs index 56cc84b..232317d 100644 --- a/mir/src/tyctxt.rs +++ b/mir/src/tyctxt.rs @@ -164,28 +164,28 @@ pub fn adt_impl_printf_debug(adt:&Adt,id:TyId)->String{ res.push_str(&format!("fld{field_id},")); } res.push_str("}=>{\n"); - res.push_str(&format!("unsafe{{printf(\"Variant{variant_idx}{{\".as_ptr() as *const c_char)}};\n")); + res.push_str(&format!("unsafe{{printf(\"Variant{variant_idx}{{\\0\".as_ptr() as *const c_char)}};\n")); // Iterate trough fields to print values of fields of variant for (field_id,_) in variant.fields.iter().enumerate(){ - res.push_str(&format!("\t\tunsafe{{printf(\"fld{field_id}:\".as_ptr() as *const c_char)}};\n")); + res.push_str(&format!("\t\tunsafe{{printf(\"fld{field_id}:\\0\".as_ptr() as *const c_char)}};\n")); res.push_str(&format!("\t\tfld{field_id}.printf_debug();\n")); - res.push_str("unsafe{printf(\",\".as_ptr() as *const c_char)};\n"); + res.push_str("unsafe{printf(\",\\0\".as_ptr() as *const c_char)};\n"); } res.push_str("},\n") } res.push_str("\t\t}\n"); - res.push_str("unsafe{printf(\"}\".as_ptr() as *const c_char)};\n"); + res.push_str("unsafe{printf(\"\\0}\".as_ptr() as *const c_char)};\n"); res.push_str("\t}\n}"); res } else{ // Formats a struct - let mut res = format!("impl PrintFDebug for {name}{{\n\tunsafe fn printf_debug(&self){{\n\tunsafe{{printf(\"{name}{{\0\".as_ptr() as *const c_char)}};",name = id.type_name()); + let mut res = format!("impl PrintFDebug for {name}{{\n\tunsafe fn printf_debug(&self){{\n\tunsafe{{printf(\"{name}{{\\0\".as_ptr() as *const c_char)}};",name = id.type_name()); // Iterate trough fields to print values of fields of stuct for (field_id,_) in adt.variants[0].fields.iter().enumerate(){ format!("\n\tprintf(\"fld{field_id}:\\0\".as_ptr() as *const c_char);\n\tself.fld{field_id}.printf_debug();"); } - res.push_str("\n\tunsafe{printf(\"}\".as_ptr() as *const c_char)};}\n}"); + res.push_str("\n\tunsafe{printf(\"}\\0\".as_ptr() as *const c_char)};}\n}"); res }; format!("{res}\n#[derive(Copy,Clone)]") From eaf5b10fd036e9af58fe19aebac45e968bf0bd3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kostrubiec?= Date: Sat, 11 May 2024 13:52:09 +0200 Subject: [PATCH 13/20] Fixed printing of NaN values using printf printing the sign of a NaN. Fixed issues with printing struct members --- mir/src/syntax.rs | 31 +++++++++++++++++++++++++------ mir/src/tyctxt.rs | 4 ++-- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/mir/src/syntax.rs b/mir/src/syntax.rs index dd2828e..bf02a03 100644 --- a/mir/src/syntax.rs +++ b/mir/src/syntax.rs @@ -814,14 +814,33 @@ impl Program { printf("%i\0".as_ptr() as *const c_char,*self); } } - impl PrintFDebug for f32{ - unsafe fn printf_debug(&self){ - printf("%f\0".as_ptr() as *const c_char,*self as core::ffi::c_double); + impl PrintFDebug for f32 { + unsafe fn printf_debug(&self) { + if self.is_nan(){ + printf( + "NaN\0".as_ptr() as *const c_char, + ); + }else{ + printf( + "%f\0".as_ptr() as *const c_char, + *self as core::ffi::c_double, + ); + } + } } - impl PrintFDebug for f64{ - unsafe fn printf_debug(&self){ - printf("%f\0".as_ptr() as *const c_char,*self as core::ffi::c_double); + impl PrintFDebug for f64 { + unsafe fn printf_debug(&self) { + if self.is_nan(){ + printf( + "NaN\0".as_ptr() as *const c_char, + ); + }else{ + printf( + "%f\0".as_ptr() as *const c_char, + *self as core::ffi::c_double, + ); + } } } impl PrintFDebug for [T;N]{ diff --git a/mir/src/tyctxt.rs b/mir/src/tyctxt.rs index 232317d..20e3ed2 100644 --- a/mir/src/tyctxt.rs +++ b/mir/src/tyctxt.rs @@ -181,9 +181,9 @@ pub fn adt_impl_printf_debug(adt:&Adt,id:TyId)->String{ else{ // Formats a struct let mut res = format!("impl PrintFDebug for {name}{{\n\tunsafe fn printf_debug(&self){{\n\tunsafe{{printf(\"{name}{{\\0\".as_ptr() as *const c_char)}};",name = id.type_name()); - // Iterate trough fields to print values of fields of stuct + // Iterate trough fields to print values of fields of stuct for (field_id,_) in adt.variants[0].fields.iter().enumerate(){ - format!("\n\tprintf(\"fld{field_id}:\\0\".as_ptr() as *const c_char);\n\tself.fld{field_id}.printf_debug();"); + res.push_str(format!("\n\tprintf(\"fld{field_id}:\\0\".as_ptr() as *const c_char);\n\tself.fld{field_id}.printf_debug();")); } res.push_str("\n\tunsafe{printf(\"}\\0\".as_ptr() as *const c_char)};}\n}"); res From c843fb6bfbcd5b9175ed264bce3515d02ba5c814 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kostrubiec?= Date: Sat, 11 May 2024 13:52:49 +0200 Subject: [PATCH 14/20] Small fix --- mir/src/tyctxt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mir/src/tyctxt.rs b/mir/src/tyctxt.rs index 20e3ed2..3d81810 100644 --- a/mir/src/tyctxt.rs +++ b/mir/src/tyctxt.rs @@ -183,7 +183,7 @@ pub fn adt_impl_printf_debug(adt:&Adt,id:TyId)->String{ let mut res = format!("impl PrintFDebug for {name}{{\n\tunsafe fn printf_debug(&self){{\n\tunsafe{{printf(\"{name}{{\\0\".as_ptr() as *const c_char)}};",name = id.type_name()); // Iterate trough fields to print values of fields of stuct for (field_id,_) in adt.variants[0].fields.iter().enumerate(){ - res.push_str(format!("\n\tprintf(\"fld{field_id}:\\0\".as_ptr() as *const c_char);\n\tself.fld{field_id}.printf_debug();")); + res.push_str(&format!("\n\tprintf(\"fld{field_id}:\\0\".as_ptr() as *const c_char);\n\tself.fld{field_id}.printf_debug();")); } res.push_str("\n\tunsafe{printf(\"}\\0\".as_ptr() as *const c_char)};}\n}"); res From 350b556dd198d9c27dff22e02b88d5a787fbc289 Mon Sep 17 00:00:00 2001 From: Andy Wang Date: Mon, 14 Oct 2024 23:24:42 +0100 Subject: [PATCH 15/20] Update CITATION.cff --- CITATION.cff | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/CITATION.cff b/CITATION.cff index 1538a84..4969f77 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -1,30 +1,24 @@ cff-version: 1.2.0 title: Rustlantis -message: A Rust Mid-level Intermediate Representation fuzzer +message: A fuzzer for the Rust compiler type: software authors: - - given-names: Andy + - given-names: Qian (Andy) family-names: Wang - affiliation: ETH Zürich orcid: 'https://orcid.org/0009-0006-0779-8651' + affiliation: ETH Zürich - given-names: Ralf family-names: Jung - affiliation: ETH Zürich orcid: 'https://orcid.org/0000-0001-7669-6348' + affiliation: ETH Zürich identifiers: - - type: url - value: >- - https://ethz.ch/content/dam/ethz/special-interest/infk/inst-pls/plf-dam/documents/StudentProjects/MasterTheses/2023-Andy-Thesis.pdf + - type: doi + value: 10.1145/3689780 repository-code: 'https://github.com/cbeuw/rustlantis' -abstract: >- - Rustlantis is a novel fuzzer capable of generating - programs in Rust’s Mid-level Intermediate Representation - that are deterministic and free from Undefined Behaviour. keywords: + - Compiler testing - Rust - - fuzzing - - software validation - - compilers + - Fuzzing license: - - Apache-2.0 - - MIT + - Apache-2.0 + - MIT From 8183b5aef7d672baa01b67cf982a89facdad3e3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kostrubiec?= Date: Tue, 12 Nov 2024 22:02:32 +0100 Subject: [PATCH 16/20] FIxed issues with dumper caused by the merge. --- generate/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generate/src/main.rs b/generate/src/main.rs index 02efb12..83abe49 100644 --- a/generate/src/main.rs +++ b/generate/src/main.rs @@ -13,7 +13,7 @@ mod mem; mod place_select; mod pgraph; mod ty; - +use mir::VarDumper; use std::time::Instant; use clap::{arg, command, value_parser, Arg}; From 87cb1c4fc8fce8db12acdf110475b0dee1c6b0ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kostrubiec?= Date: Sun, 1 Dec 2024 21:55:48 +0100 Subject: [PATCH 17/20] Some initial work on generating source files compatible with rust-gpu --- generate/src/generation/mod.rs | 2 +- generate/src/main.rs | 7 +- mir/src/lib.rs | 4 +- mir/src/serialize.rs | 37 +++- mir/src/syntax.rs | 390 ++++++++++++++++++++++++++++++++- mir/src/tyctxt.rs | 58 +++-- 6 files changed, 465 insertions(+), 33 deletions(-) diff --git a/generate/src/generation/mod.rs b/generate/src/generation/mod.rs index d265b60..e6c37d3 100644 --- a/generate/src/generation/mod.rs +++ b/generate/src/generation/mod.rs @@ -991,7 +991,7 @@ impl GenerationCtx { for vars in dumpped.chunks(Program::DUMPER_ARITY) { let new_bb = self.add_new_bb(); - let args = if self.program.var_dumper == VarDumper::StdVarDumper || self.program.var_dumper == VarDumper::PrintfVarDumper{ + let args = if matches!(self.program.var_dumper,VarDumper::StdVarDumper | VarDumper::PrintfVarDumper{..}){ let mut args = Vec::with_capacity(1 + Program::DUMPER_ARITY * 2); args.push(Operand::Constant( self.cursor.function.index().try_into().unwrap(), diff --git a/generate/src/main.rs b/generate/src/main.rs index 83abe49..ba4dd10 100644 --- a/generate/src/main.rs +++ b/generate/src/main.rs @@ -29,7 +29,7 @@ fn main() { arg!(-d --debug "generate a program where values are printed instead of hashed (slow)"), arg!(-p --printf_debug "generate a program where values are printed using the C 'printf' function instead of hashed (slow)"), - + arg!(-g --rust_gpu "generate a program where values are printed using the C 'printf' function instead of hashed (slow)"), Arg::new("call-syntax") .long("call-syntax") .value_parser(["v1", "v2", "v3", "v4"]) @@ -44,11 +44,12 @@ fn main() { .get_one::("seed") .expect("need an integer as seed"); let debug_dump = matches.get_one::("debug").copied().unwrap_or(false); - let printf_dump = matches.get_one::("printf_debug").copied().unwrap_or(false); + let rust_gpu = matches.get_one::("rust_gpu").copied().unwrap_or(false); + let printf_dump = matches.get_one::("printf_debug").copied().unwrap_or(false) | rust_gpu; let dumper = match (debug_dump,printf_dump){ (false,false)=>VarDumper::HashDumper, (true,false)=>VarDumper::StdVarDumper, - (false,true)=>VarDumper::PrintfVarDumper, + (false,true)=>VarDumper::PrintfVarDumper{rust_gpu}, (true,true)=>panic!("You can only choose either the `debug` dumper or `printf_debug` dumper, but both of them have been selected."), }; info!("Generating a program with seed {seed}"); diff --git a/mir/src/lib.rs b/mir/src/lib.rs index 672f7dc..ea2b6f7 100644 --- a/mir/src/lib.rs +++ b/mir/src/lib.rs @@ -11,6 +11,6 @@ pub enum VarDumper{ HashDumper, /// Print variables using standard rust formatting StdVarDumper, - /// Print variables using the c `printf` function - PrintfVarDumper, + /// Print variables using the c `printf` function. If `rust_gpu` is true, then use the `printf!()` rust-gpu macro instead of `printf` + PrintfVarDumper{rust_gpu:bool}, } \ No newline at end of file diff --git a/mir/src/serialize.rs b/mir/src/serialize.rs index 7a49587..355e4fc 100644 --- a/mir/src/serialize.rs +++ b/mir/src/serialize.rs @@ -368,12 +368,19 @@ impl Body { impl Program { pub fn serialize(&self, tcx: &TyCtxt, call_syntax: CallSynatx) -> String { - let mut program = Program::HEADER.to_string(); + let mut program =match self.var_dumper{ + VarDumper::PrintfVarDumper{rust_gpu:true}=>Program::NOSTD_HEADER.to_string(), + _=> Program::HEADER.to_string(), + }; program += match self.var_dumper{ VarDumper::HashDumper=>Program::DUMPER, VarDumper::StdVarDumper=>Program::DEBUG_DUMPER, - VarDumper::PrintfVarDumper=>Program::PRINTF_DUMPER, + VarDumper::PrintfVarDumper{rust_gpu:false}=>Program::PRINTF_DUMPER, + VarDumper::PrintfVarDumper{rust_gpu:true}=>Program::RUSTGPU_PRINTF_DUMPER, }; + if let VarDumper::PrintfVarDumper { rust_gpu:true } = self.var_dumper { + program += "use spirv_std::*;\n"; + } program.extend(self.functions.iter_enumerated().map(|(idx, body)| { let args_list: String = body .args_iter() @@ -401,7 +408,7 @@ impl Program { let arg_list: String = self .entry_args .iter() - .map(|arg| format!("std::hint::black_box({})", arg.serialize(tcx))) + .map(|arg| format!("core::hint::black_box({})", arg.serialize(tcx))) .intersperse(", ".to_string()) .collect(); @@ -421,13 +428,23 @@ impl Program { } "# }; - - program.push_str(&format!( - "pub fn main() {{ - {first_fn}({arg_list}); - {hash_printer} - }}" - )); + if let VarDumper::PrintfVarDumper { rust_gpu:true } = self.var_dumper { + program.push_str(&format!( + "#[spirv(compute(threads(1)))] + pub fn main() {{ + {first_fn}({arg_list}); + {hash_printer} + }}" + )); + } else{ + program.push_str(&format!( + "pub fn main() {{ + {first_fn}({arg_list}); + {hash_printer} + }}" + )); + } + program } } diff --git a/mir/src/syntax.rs b/mir/src/syntax.rs index bf02a03..28c7f9a 100644 --- a/mir/src/syntax.rs +++ b/mir/src/syntax.rs @@ -718,11 +718,15 @@ impl Program { pub const FUNCTION_ATTRIBUTE: &'static str = "#[custom_mir(dialect = \"runtime\", phase = \"initial\")]"; pub const HEADER: &'static str = "#![recursion_limit = \"1024\"] - #![feature(custom_mir, core_intrinsics, const_hash)] + #![feature(custom_mir, core_intrinsics)] #![allow(unused_parens, unused_assignments, overflowing_literals,internal_features)] extern crate core; use core::intrinsics::mir::*;\n"; - + pub const NOSTD_HEADER: &'static str = "#![recursion_limit = \"1024\"] + #![feature(custom_mir, core_intrinsics)] + #![allow(unused_parens, unused_assignments, overflowing_literals,internal_features)] + #![no_std] + use core::intrinsics::mir::*;\n"; pub const DUMPER: &'static str = r#" use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; @@ -759,9 +763,9 @@ impl Program { println!("fn{f}:_{var0} = {val0:?}\n_{var1} = {val1:?}\n_{var2} = {val2:?}\n_{var3} = {val3:?}"); } "#; - // Implements printf based debuggig for primitive types. + /// Implements printf based debuggig for primitive types. pub const PRINTF_DUMPER: &'static str = r#" - use std::ffi::{c_char, c_int}; + use core::ffi::{c_char, c_int}; extern "C" { fn printf(fmt: *const c_char, ...) -> c_int; @@ -1145,6 +1149,384 @@ impl Program { } } "#; + /// Implements printf based debuggig for primitive types. + pub const RUSTGPU_PRINTF_DUMPER: &'static str = r#" + use core::ffi::{c_char, c_int}; + trait PrintFDebug{ + unsafe fn printf_debug(&self); + } + impl PrintFDebug for *const T{ + unsafe fn printf_debug(&self){ + unsafe{(**self).printf_debug()}; + } + } + impl PrintFDebug for *mut T{ + unsafe fn printf_debug(&self){ + unsafe{(**self).printf_debug()}; + } + } + impl PrintFDebug for &T{ + unsafe fn printf_debug(&self){ + (**self).printf_debug(); + } + } + impl PrintFDebug for &mut T{ + unsafe fn printf_debug(&self){ + (**self).printf_debug(); + } + } + impl PrintFDebug for i8{ + unsafe fn printf_debug(&self){ + printf!("%i",*self as c_int); + } + } + impl PrintFDebug for u8{ + unsafe fn printf_debug(&self){ + printf!("%u",*self as c_uint); + } + } + impl PrintFDebug for i16{ + unsafe fn printf_debug(&self){ + printf!("%i",*self as c_int); + } + } + impl PrintFDebug for u16{ + unsafe fn printf_debug(&self){ + printf!("%u",*self as c_uint); + } + } + impl PrintFDebug for i32{ + unsafe fn printf_debug(&self){ + printf!("%i",*self as c_int); + } + } + impl PrintFDebug for f32 { + unsafe fn printf_debug(&self) { + if self.is_nan(){ + printf!("NaN"); + }else{ + printf!( + "%f", + *self as core::ffi::c_double, + ); + } + + } + } + impl PrintFDebug for f64 { + unsafe fn printf_debug(&self) { + if self.is_nan(){ + printf!("NaN"); + }else{ + printf!( + "%f", + *self as core::ffi::c_double, + ); + } + } + } + impl PrintFDebug for [T;N]{ + unsafe fn printf_debug(&self){ + printf!("["); + for b in self{ + b.printf_debug(); + printf!(","); + } + printf!("]"); + } + } + impl PrintFDebug for u32{ + unsafe fn printf_debug(&self){ + printf!("%u",*self as c_uint); + } + } + impl PrintFDebug for char{ + unsafe fn printf_debug(&self){ + printf!("%u",*self as u32 as c_uint); + } + } + impl PrintFDebug for i64{ + unsafe fn printf_debug(&self){ + printf!("%li",*self as c_long); + } + } + impl PrintFDebug for u64{ + unsafe fn printf_debug(&self){ + printf!("%lu",*self); + } + } + impl PrintFDebug for i128{ + unsafe fn printf_debug(&self){ + u128::printf_debug(&(*self as u128)); + } + } + impl PrintFDebug for u128{ + unsafe fn printf_debug(&self){ + printf!("%lx%lx", (*self >> 64) as u64,*self as u64); + } + } + impl PrintFDebug for isize{ + unsafe fn printf_debug(&self){ + printf!("%li",*self as i64) + } + } + impl PrintFDebug for usize{ + unsafe fn printf_debug(&self){ + printf!("%lu".as_ptr(),*self as u64); + } + } + impl PrintFDebug for bool{ + unsafe fn printf_debug(&self){ + if *self{ + printf!("true"); + } + else{ + printf!("false"); + } + } + } + impl PrintFDebug for (){ + unsafe fn printf_debug(&self){ + printf!("()"); + } + } + impl PrintFDebug for (A,){ + unsafe fn printf_debug(&self){ + printf!("("); + self.0.printf_debug(); + printf!(",)"); + } + } + impl PrintFDebug for (A,B){ + unsafe fn printf_debug(&self){ + printf!("("); + self.0.printf_debug(); + printf!(","); + self.1.printf_debug(); + printf!(")"); + } + } + impl PrintFDebug for (A,B,C){ + unsafe fn printf_debug(&self){ + printf!("("); + self.0.printf_debug(); + printf!(","); + self.1.printf_debug(); + printf!(","); + self.2.printf_debug(); + printf!(")"); + } + } + impl PrintFDebug for (A,B,C,D){ + unsafe fn printf_debug(&self){ + printf!("("); + self.0.printf_debug(); + printf!(","); + self.1.printf_debug(); + printf!(","); + self.2.printf_debug(); + printf!(","); + self.3.printf_debug(); + printf!(")"); + } + } + impl PrintFDebug for (A,B,C,D,E){ + unsafe fn printf_debug(&self){ + printf!("("); + self.0.printf_debug(); + printf!(","); + self.1.printf_debug(); + printf!(","); + self.2.printf_debug(); + printf!(","); + self.3.printf_debug(); + printf!(","); + self.4.printf_debug(); + printf!(")"); + } + } + impl PrintFDebug for (A,B,C,D,E,F){ + unsafe fn printf_debug(&self){ + printf!("("); + self.0.printf_debug(); + printf!(","); + self.1.printf_debug(); + printf!(","); + self.2.printf_debug(); + printf!(","); + self.3.printf_debug(); + printf!(","); + self.4.printf_debug(); + printf!(","); + self.5.printf_debug(); + printf!(")"); + } + } + impl PrintFDebug for (A,B,C,D,E,F,G){ + unsafe fn printf_debug(&self){ + printf!("("); + self.0.printf_debug(); + printf!(","); + self.1.printf_debug(); + printf!(","); + self.2.printf_debug(); + printf!(","); + self.3.printf_debug(); + printf!(","); + self.4.printf_debug(); + printf!(","); + self.5.printf_debug(); + printf!(","); + self.6.printf_debug(); + printf!(")"); + } + } + impl PrintFDebug for (A,B,C,D,E,F,G,H){ + unsafe fn printf_debug(&self){ + printf!("("); + self.0.printf_debug(); + printf!(","); + self.1.printf_debug(); + printf!(","); + self.2.printf_debug(); + printf!(","); + self.3.printf_debug(); + printf!(","); + self.4.printf_debug(); + printf!(","); + self.5.printf_debug(); + printf!(","); + self.6.printf_debug(); + printf!(","); + self.7.printf_debug(); + printf!(")"); + } + } + impl PrintFDebug for (A,B,C,D,E,F,G,H,I){ + unsafe fn printf_debug(&self){ + printf!("("); + self.0.printf_debug(); + printf!(","); + self.1.printf_debug(); + printf!(","); + self.2.printf_debug(); + printf!(","); + self.3.printf_debug(); + printf!(","); + self.4.printf_debug(); + printf!(","); + self.5.printf_debug(); + printf!(","); + self.6.printf_debug(); + printf!(","); + self.7.printf_debug(); + printf!(","); + self.8.printf_debug(); + printf!(")"); + } + } + impl PrintFDebug for (A,B,C,D,E,F,G,H,I,J){ + unsafe fn printf_debug(&self){ + printf!("("); + self.0.printf_debug(); + printf!(","); + self.1.printf_debug(); + printf!(","); + self.2.printf_debug(); + printf!(","); + self.3.printf_debug(); + printf!(","); + self.4.printf_debug(); + printf!(","); + self.5.printf_debug(); + printf!(","); + self.6.printf_debug(); + printf!(","); + self.7.printf_debug(); + printf!(","); + self.8.printf_debug(); + printf!(","); + self.9.printf_debug(); + printf!(")"); + } + } + impl PrintFDebug for (A,B,C,D,E,F,G,H,I,J,K){ + unsafe fn printf_debug(&self){ + printf!("("); + self.0.printf_debug(); + printf!(","); + self.1.printf_debug(); + printf!(","); + self.2.printf_debug(); + printf!(","); + self.3.printf_debug(); + printf!(","); + self.4.printf_debug(); + printf!(","); + self.5.printf_debug(); + printf!(","); + self.6.printf_debug(); + printf!(","); + self.7.printf_debug(); + printf!(","); + self.8.printf_debug(); + printf!(","); + self.9.printf_debug(); + printf!(","); + self.10.printf_debug(); + printf!(")"); + } + } + impl PrintFDebug for (A,B,C,D,E,F,G,H,I,J,K,L){ + unsafe fn printf_debug(&self){ + printf!("("); + self.0.printf_debug(); + printf!(","); + self.1.printf_debug(); + printf!(","); + self.2.printf_debug(); + printf!(","); + self.3.printf_debug(); + printf!(","); + self.4.printf_debug(); + printf!(","); + self.5.printf_debug(); + printf!(","); + self.6.printf_debug(); + printf!(","); + self.7.printf_debug(); + printf!(","); + self.8.printf_debug(); + printf!(","); + self.9.printf_debug(); + printf!(","); + self.10.printf_debug(); + printf!(","); + self.11.printf_debug(); + printf!(")"); + } + } + #[inline(never)] + fn dump_var( + f: usize, + var0: usize, val0: impl PrintFDebug, + var1: usize, val1: impl PrintFDebug, + var2: usize, val2: impl PrintFDebug, + var3: usize, val3: impl PrintFDebug, + ) { + unsafe{ + printf!("fn%u:_%u = ",f,var0); + val0.printf_debug(); + printf!("\n_%u = ",var1); + val1.printf_debug(); + printf!("\n_%u = ",var2); + val2.printf_debug(); + printf!("\n_%u = ",var3); + val3.printf_debug(); + printf!("\n"); + } + } + "#; // Fake "intrinsic" pub const DUMPER_CALL: Callee = Callee::Named("dump_var"); pub const DUMPER_ARITY: usize = 4; diff --git a/mir/src/tyctxt.rs b/mir/src/tyctxt.rs index 3d81810..4e1ac8f 100644 --- a/mir/src/tyctxt.rs +++ b/mir/src/tyctxt.rs @@ -123,7 +123,7 @@ impl TyCtxt { // `Debug` derive is ommited for printf-based dumping. An implemntation of the PrintFDebug trait is emmited instead. str += &match dumper{ VarDumper::HashDumper | VarDumper::StdVarDumper => self.adt_meta[&id].derive_attrs(), - VarDumper::PrintfVarDumper => adt_impl_printf_debug(adt,id), + VarDumper::PrintfVarDumper{rust_gpu} => adt_impl_printf_debug(adt,id,rust_gpu), }; if adt.is_enum() { let variants: String = adt @@ -147,14 +147,19 @@ impl TyCtxt { str } } -// Implements the PrintFDebug trait for an ADT. -// This trait is used to dump variables using `printf` -pub fn adt_impl_printf_debug(adt:&Adt,id:TyId)->String{ +/// Implements the PrintFDebug trait for an ADT. +/// This trait is used to dump variables using `printf` +pub fn adt_impl_printf_debug(adt:&Adt,id:TyId,rust_gpu:bool)->String{ let res = if adt.is_enum() { // Formats an enum let name = id.type_name(); let mut res = format!("impl PrintFDebug for {name}{{\n\tunsafe fn printf_debug(&self){{"); - res.push_str(&format!("unsafe{{printf(\"{name}::\\0\".as_ptr() as *const c_char)}};")); + if rust_gpu{ + res.push_str(&format!("unsafe{{printf!(\"{name}::\".as_ptr())}};")); + }else{ + res.push_str(&format!("unsafe{{printf(\"{name}::\\0\".as_ptr() as *const c_char)}};")); + } + res.push_str("match self{\n"); // Iterate through variants cratete a match statement for (variant_idx,variant) in adt.variants.iter().enumerate(){ @@ -164,28 +169,55 @@ pub fn adt_impl_printf_debug(adt:&Adt,id:TyId)->String{ res.push_str(&format!("fld{field_id},")); } res.push_str("}=>{\n"); - res.push_str(&format!("unsafe{{printf(\"Variant{variant_idx}{{\\0\".as_ptr() as *const c_char)}};\n")); + if rust_gpu{ + res.push_str(&format!("unsafe{{printf!(\"Variant{variant_idx}{{\")}};\n")); + }else{ + res.push_str(&format!("unsafe{{printf(\"Variant{variant_idx}{{\\0\".as_ptr() as *const c_char)}};\n")); + } + // Iterate trough fields to print values of fields of variant for (field_id,_) in variant.fields.iter().enumerate(){ - res.push_str(&format!("\t\tunsafe{{printf(\"fld{field_id}:\\0\".as_ptr() as *const c_char)}};\n")); - res.push_str(&format!("\t\tfld{field_id}.printf_debug();\n")); - res.push_str("unsafe{printf(\",\\0\".as_ptr() as *const c_char)};\n"); + if rust_gpu{ + res.push_str(&format!("\t\tunsafe{{printf!(\"fld{field_id}:\")}};\n")); + res.push_str(&format!("\t\tfld{field_id}.printf_debug();\n")); + res.push_str("unsafe{printf!(\",\")};\n"); + }else{ + res.push_str(&format!("\t\tunsafe{{printf(\"fld{field_id}:\\0\".as_ptr() as *const c_char)}};\n")); + res.push_str(&format!("\t\tfld{field_id}.printf_debug();\n")); + res.push_str("unsafe{printf(\",\\0\".as_ptr() as *const c_char)};\n"); + } + } res.push_str("},\n") } res.push_str("\t\t}\n"); - res.push_str("unsafe{printf(\"\\0}\".as_ptr() as *const c_char)};\n"); + if rust_gpu{ + res.push_str("unsafe{printf!(\"}\")};\n"); + }else{ + res.push_str("unsafe{printf(\"\\0}\".as_ptr() as *const c_char)};\n"); + } + res.push_str("\t}\n}"); res } else{ // Formats a struct - let mut res = format!("impl PrintFDebug for {name}{{\n\tunsafe fn printf_debug(&self){{\n\tunsafe{{printf(\"{name}{{\\0\".as_ptr() as *const c_char)}};",name = id.type_name()); + let mut res = if rust_gpu{ + format!("impl PrintFDebug for {name}{{\n\tunsafe fn printf_debug(&self){{\n\tunsafe{{printf!(\"{name}{{\")}};",name = id.type_name()) + }else{format!("impl PrintFDebug for {name}{{\n\tunsafe fn printf_debug(&self){{\n\tunsafe{{printf(\"{name}{{\\0\".as_ptr() as *const c_char)}};",name = id.type_name())}; // Iterate trough fields to print values of fields of stuct for (field_id,_) in adt.variants[0].fields.iter().enumerate(){ - res.push_str(&format!("\n\tprintf(\"fld{field_id}:\\0\".as_ptr() as *const c_char);\n\tself.fld{field_id}.printf_debug();")); + if rust_gpu{ + res.push_str(&format!("\n\tprintf!(\"fld{field_id}:\");\n\tself.fld{field_id}.printf_debug();")); + }else{ + res.push_str(&format!("\n\tprintf(\"fld{field_id}:\\0\".as_ptr() as *const c_char);\n\tself.fld{field_id}.printf_debug();")); + } + } + if rust_gpu{ + res.push_str("\n\tunsafe{printf!(\"}\")};}\n}");} + else{ + res.push_str("\n\tunsafe{printf(\"}\\0\".as_ptr() as *const c_char)};}\n}"); } - res.push_str("\n\tunsafe{printf(\"}\\0\".as_ptr() as *const c_char)};}\n}"); res }; format!("{res}\n#[derive(Copy,Clone)]") From b3726ac062a339e78ecacf2c7c54284d8a20e150 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kostrubiec?= Date: Sun, 1 Dec 2024 23:34:32 +0100 Subject: [PATCH 18/20] Misc fixes to the rustgpu support. --- mir/src/lib.rs | 2 +- mir/src/serialize.rs | 2 +- mir/src/syntax.rs | 250 ++++++++++++++++++++++--------------------- mir/src/tyctxt.rs | 16 +-- 4 files changed, 140 insertions(+), 130 deletions(-) diff --git a/mir/src/lib.rs b/mir/src/lib.rs index ea2b6f7..3c7fd8b 100644 --- a/mir/src/lib.rs +++ b/mir/src/lib.rs @@ -11,6 +11,6 @@ pub enum VarDumper{ HashDumper, /// Print variables using standard rust formatting StdVarDumper, - /// Print variables using the c `printf` function. If `rust_gpu` is true, then use the `printf!()` rust-gpu macro instead of `printf` + /// Print variables using the c `printf` function. If `rust_gpu` is true, then use the `debug_printf!()` rust-gpu macro instead of `printf` PrintfVarDumper{rust_gpu:bool}, } \ No newline at end of file diff --git a/mir/src/serialize.rs b/mir/src/serialize.rs index 355e4fc..fb72329 100644 --- a/mir/src/serialize.rs +++ b/mir/src/serialize.rs @@ -379,7 +379,7 @@ impl Program { VarDumper::PrintfVarDumper{rust_gpu:true}=>Program::RUSTGPU_PRINTF_DUMPER, }; if let VarDumper::PrintfVarDumper { rust_gpu:true } = self.var_dumper { - program += "use spirv_std::*;\n"; + program += "use spirv_std::{spirv,macros::debug_printf};\n"; } program.extend(self.functions.iter_enumerated().map(|(idx, body)| { let args_list: String = body diff --git a/mir/src/syntax.rs b/mir/src/syntax.rs index 28c7f9a..8e8f349 100644 --- a/mir/src/syntax.rs +++ b/mir/src/syntax.rs @@ -723,7 +723,7 @@ impl Program { extern crate core; use core::intrinsics::mir::*;\n"; pub const NOSTD_HEADER: &'static str = "#![recursion_limit = \"1024\"] - #![feature(custom_mir, core_intrinsics)] + #![feature(custom_mir, core_intrinsics,asm_experimental_arch)] #![allow(unused_parens, unused_assignments, overflowing_literals,internal_features)] #![no_std] use core::intrinsics::mir::*;\n"; @@ -1151,7 +1151,7 @@ impl Program { "#; /// Implements printf based debuggig for primitive types. pub const RUSTGPU_PRINTF_DUMPER: &'static str = r#" - use core::ffi::{c_char, c_int}; + use core::ffi::{c_char, c_int,c_uint,c_long,c_ulong}; trait PrintFDebug{ unsafe fn printf_debug(&self); } @@ -1177,35 +1177,35 @@ impl Program { } impl PrintFDebug for i8{ unsafe fn printf_debug(&self){ - printf!("%i",*self as c_int); + debug_printf!("%i",*self as c_int); } } impl PrintFDebug for u8{ unsafe fn printf_debug(&self){ - printf!("%u",*self as c_uint); + debug_printf!("%u",*self as c_uint); } } impl PrintFDebug for i16{ unsafe fn printf_debug(&self){ - printf!("%i",*self as c_int); + debug_printf!("%i",*self as c_int); } } impl PrintFDebug for u16{ unsafe fn printf_debug(&self){ - printf!("%u",*self as c_uint); + debug_printf!("%u",*self as c_uint); } } impl PrintFDebug for i32{ unsafe fn printf_debug(&self){ - printf!("%i",*self as c_int); + debug_printf!("%i",*self as c_int); } } impl PrintFDebug for f32 { unsafe fn printf_debug(&self) { if self.is_nan(){ - printf!("NaN"); + debug_printf!("NaN"); }else{ - printf!( + debug_printf!( "%f", *self as core::ffi::c_double, ); @@ -1216,9 +1216,9 @@ impl Program { impl PrintFDebug for f64 { unsafe fn printf_debug(&self) { if self.is_nan(){ - printf!("NaN"); + debug_printf!("NaN"); }else{ - printf!( + debug_printf!( "%f", *self as core::ffi::c_double, ); @@ -1227,32 +1227,36 @@ impl Program { } impl PrintFDebug for [T;N]{ unsafe fn printf_debug(&self){ - printf!("["); + debug_printf!("["); for b in self{ b.printf_debug(); - printf!(","); + debug_printf!(","); } - printf!("]"); + debug_printf!("]"); } } impl PrintFDebug for u32{ unsafe fn printf_debug(&self){ - printf!("%u",*self as c_uint); + debug_printf!("%u",*self as c_uint); } } impl PrintFDebug for char{ unsafe fn printf_debug(&self){ - printf!("%u",*self as u32 as c_uint); + debug_printf!("%u",*self as u32 as c_uint); } } impl PrintFDebug for i64{ unsafe fn printf_debug(&self){ - printf!("%li",*self as c_long); + if *self < 0{ + debug_printf!("-%lu",*(-self) as c_ulong); + } + else{ + debug_printf!("%lu",*self as c_ulong);} } } impl PrintFDebug for u64{ unsafe fn printf_debug(&self){ - printf!("%lu",*self); + debug_printf!("%lu",*self); } } impl PrintFDebug for i128{ @@ -1262,248 +1266,254 @@ impl Program { } impl PrintFDebug for u128{ unsafe fn printf_debug(&self){ - printf!("%lx%lx", (*self >> 64) as u64,*self as u64); + debug_printf!("%lx%lx", (*self >> 64) as u64,*self as u64); } } impl PrintFDebug for isize{ unsafe fn printf_debug(&self){ - printf!("%li",*self as i64) - } + + if *self < 0{ + debug_printf!("-%lu",*(-self) as c_ulong); + } + else{ + debug_printf!("%lu",*self as c_ulong);} + } + } impl PrintFDebug for usize{ unsafe fn printf_debug(&self){ - printf!("%lu".as_ptr(),*self as u64); + debug_printf!("%lu",*self as u64); } } impl PrintFDebug for bool{ unsafe fn printf_debug(&self){ if *self{ - printf!("true"); + debug_printf!("true"); } else{ - printf!("false"); + debug_printf!("false"); } } } impl PrintFDebug for (){ unsafe fn printf_debug(&self){ - printf!("()"); + debug_printf!("()"); } } impl PrintFDebug for (A,){ unsafe fn printf_debug(&self){ - printf!("("); + debug_printf!("("); self.0.printf_debug(); - printf!(",)"); + debug_printf!(",)"); } } impl PrintFDebug for (A,B){ unsafe fn printf_debug(&self){ - printf!("("); + debug_printf!("("); self.0.printf_debug(); - printf!(","); + debug_printf!(","); self.1.printf_debug(); - printf!(")"); + debug_printf!(")"); } } impl PrintFDebug for (A,B,C){ unsafe fn printf_debug(&self){ - printf!("("); + debug_printf!("("); self.0.printf_debug(); - printf!(","); + debug_printf!(","); self.1.printf_debug(); - printf!(","); + debug_printf!(","); self.2.printf_debug(); - printf!(")"); + debug_printf!(")"); } } impl PrintFDebug for (A,B,C,D){ unsafe fn printf_debug(&self){ - printf!("("); + debug_printf!("("); self.0.printf_debug(); - printf!(","); + debug_printf!(","); self.1.printf_debug(); - printf!(","); + debug_printf!(","); self.2.printf_debug(); - printf!(","); + debug_printf!(","); self.3.printf_debug(); - printf!(")"); + debug_printf!(")"); } } impl PrintFDebug for (A,B,C,D,E){ unsafe fn printf_debug(&self){ - printf!("("); + debug_printf!("("); self.0.printf_debug(); - printf!(","); + debug_printf!(","); self.1.printf_debug(); - printf!(","); + debug_printf!(","); self.2.printf_debug(); - printf!(","); + debug_printf!(","); self.3.printf_debug(); - printf!(","); + debug_printf!(","); self.4.printf_debug(); - printf!(")"); + debug_printf!(")"); } } impl PrintFDebug for (A,B,C,D,E,F){ unsafe fn printf_debug(&self){ - printf!("("); + debug_printf!("("); self.0.printf_debug(); - printf!(","); + debug_printf!(","); self.1.printf_debug(); - printf!(","); + debug_printf!(","); self.2.printf_debug(); - printf!(","); + debug_printf!(","); self.3.printf_debug(); - printf!(","); + debug_printf!(","); self.4.printf_debug(); - printf!(","); + debug_printf!(","); self.5.printf_debug(); - printf!(")"); + debug_printf!(")"); } } impl PrintFDebug for (A,B,C,D,E,F,G){ unsafe fn printf_debug(&self){ - printf!("("); + debug_printf!("("); self.0.printf_debug(); - printf!(","); + debug_printf!(","); self.1.printf_debug(); - printf!(","); + debug_printf!(","); self.2.printf_debug(); - printf!(","); + debug_printf!(","); self.3.printf_debug(); - printf!(","); + debug_printf!(","); self.4.printf_debug(); - printf!(","); + debug_printf!(","); self.5.printf_debug(); - printf!(","); + debug_printf!(","); self.6.printf_debug(); - printf!(")"); + debug_printf!(")"); } } impl PrintFDebug for (A,B,C,D,E,F,G,H){ unsafe fn printf_debug(&self){ - printf!("("); + debug_printf!("("); self.0.printf_debug(); - printf!(","); + debug_printf!(","); self.1.printf_debug(); - printf!(","); + debug_printf!(","); self.2.printf_debug(); - printf!(","); + debug_printf!(","); self.3.printf_debug(); - printf!(","); + debug_printf!(","); self.4.printf_debug(); - printf!(","); + debug_printf!(","); self.5.printf_debug(); - printf!(","); + debug_printf!(","); self.6.printf_debug(); - printf!(","); + debug_printf!(","); self.7.printf_debug(); - printf!(")"); + debug_printf!(")"); } } impl PrintFDebug for (A,B,C,D,E,F,G,H,I){ unsafe fn printf_debug(&self){ - printf!("("); + debug_printf!("("); self.0.printf_debug(); - printf!(","); + debug_printf!(","); self.1.printf_debug(); - printf!(","); + debug_printf!(","); self.2.printf_debug(); - printf!(","); + debug_printf!(","); self.3.printf_debug(); - printf!(","); + debug_printf!(","); self.4.printf_debug(); - printf!(","); + debug_printf!(","); self.5.printf_debug(); - printf!(","); + debug_printf!(","); self.6.printf_debug(); - printf!(","); + debug_printf!(","); self.7.printf_debug(); - printf!(","); + debug_printf!(","); self.8.printf_debug(); - printf!(")"); + debug_printf!(")"); } } impl PrintFDebug for (A,B,C,D,E,F,G,H,I,J){ unsafe fn printf_debug(&self){ - printf!("("); + debug_printf!("("); self.0.printf_debug(); - printf!(","); + debug_printf!(","); self.1.printf_debug(); - printf!(","); + debug_printf!(","); self.2.printf_debug(); - printf!(","); + debug_printf!(","); self.3.printf_debug(); - printf!(","); + debug_printf!(","); self.4.printf_debug(); - printf!(","); + debug_printf!(","); self.5.printf_debug(); - printf!(","); + debug_printf!(","); self.6.printf_debug(); - printf!(","); + debug_printf!(","); self.7.printf_debug(); - printf!(","); + debug_printf!(","); self.8.printf_debug(); - printf!(","); + debug_printf!(","); self.9.printf_debug(); - printf!(")"); + debug_printf!(")"); } } impl PrintFDebug for (A,B,C,D,E,F,G,H,I,J,K){ unsafe fn printf_debug(&self){ - printf!("("); + debug_printf!("("); self.0.printf_debug(); - printf!(","); + debug_printf!(","); self.1.printf_debug(); - printf!(","); + debug_printf!(","); self.2.printf_debug(); - printf!(","); + debug_printf!(","); self.3.printf_debug(); - printf!(","); + debug_printf!(","); self.4.printf_debug(); - printf!(","); + debug_printf!(","); self.5.printf_debug(); - printf!(","); + debug_printf!(","); self.6.printf_debug(); - printf!(","); + debug_printf!(","); self.7.printf_debug(); - printf!(","); + debug_printf!(","); self.8.printf_debug(); - printf!(","); + debug_printf!(","); self.9.printf_debug(); - printf!(","); + debug_printf!(","); self.10.printf_debug(); - printf!(")"); + debug_printf!(")"); } } impl PrintFDebug for (A,B,C,D,E,F,G,H,I,J,K,L){ unsafe fn printf_debug(&self){ - printf!("("); + debug_printf!("("); self.0.printf_debug(); - printf!(","); + debug_printf!(","); self.1.printf_debug(); - printf!(","); + debug_printf!(","); self.2.printf_debug(); - printf!(","); + debug_printf!(","); self.3.printf_debug(); - printf!(","); + debug_printf!(","); self.4.printf_debug(); - printf!(","); + debug_printf!(","); self.5.printf_debug(); - printf!(","); + debug_printf!(","); self.6.printf_debug(); - printf!(","); + debug_printf!(","); self.7.printf_debug(); - printf!(","); + debug_printf!(","); self.8.printf_debug(); - printf!(","); + debug_printf!(","); self.9.printf_debug(); - printf!(","); + debug_printf!(","); self.10.printf_debug(); - printf!(","); + debug_printf!(","); self.11.printf_debug(); - printf!(")"); + debug_printf!(")"); } } #[inline(never)] @@ -1515,15 +1525,15 @@ impl Program { var3: usize, val3: impl PrintFDebug, ) { unsafe{ - printf!("fn%u:_%u = ",f,var0); + debug_printf!("fn%lu:_%lu = ",f as u64,var0 as u64); val0.printf_debug(); - printf!("\n_%u = ",var1); + debug_printf!("\n_%lu = ",var1 as u64); val1.printf_debug(); - printf!("\n_%u = ",var2); + debug_printf!("\n_%lu = ",var2 as u64); val2.printf_debug(); - printf!("\n_%u = ",var3); + debug_printf!("\n_%lu = ",var3 as u64); val3.printf_debug(); - printf!("\n"); + debug_printf!("\n"); } } "#; diff --git a/mir/src/tyctxt.rs b/mir/src/tyctxt.rs index 4e1ac8f..560e213 100644 --- a/mir/src/tyctxt.rs +++ b/mir/src/tyctxt.rs @@ -155,7 +155,7 @@ pub fn adt_impl_printf_debug(adt:&Adt,id:TyId,rust_gpu:bool)->String{ let name = id.type_name(); let mut res = format!("impl PrintFDebug for {name}{{\n\tunsafe fn printf_debug(&self){{"); if rust_gpu{ - res.push_str(&format!("unsafe{{printf!(\"{name}::\".as_ptr())}};")); + res.push_str(&format!("unsafe{{debug_printf!(\"{name}::\")}};")); }else{ res.push_str(&format!("unsafe{{printf(\"{name}::\\0\".as_ptr() as *const c_char)}};")); } @@ -170,7 +170,7 @@ pub fn adt_impl_printf_debug(adt:&Adt,id:TyId,rust_gpu:bool)->String{ } res.push_str("}=>{\n"); if rust_gpu{ - res.push_str(&format!("unsafe{{printf!(\"Variant{variant_idx}{{\")}};\n")); + res.push_str(&format!("unsafe{{debug_printf!(\"Variant{variant_idx}{{\")}};\n")); }else{ res.push_str(&format!("unsafe{{printf(\"Variant{variant_idx}{{\\0\".as_ptr() as *const c_char)}};\n")); } @@ -178,9 +178,9 @@ pub fn adt_impl_printf_debug(adt:&Adt,id:TyId,rust_gpu:bool)->String{ // Iterate trough fields to print values of fields of variant for (field_id,_) in variant.fields.iter().enumerate(){ if rust_gpu{ - res.push_str(&format!("\t\tunsafe{{printf!(\"fld{field_id}:\")}};\n")); + res.push_str(&format!("\t\tunsafe{{debug_printf!(\"fld{field_id}:\")}};\n")); res.push_str(&format!("\t\tfld{field_id}.printf_debug();\n")); - res.push_str("unsafe{printf!(\",\")};\n"); + res.push_str("unsafe{debug_printf!(\",\")};\n"); }else{ res.push_str(&format!("\t\tunsafe{{printf(\"fld{field_id}:\\0\".as_ptr() as *const c_char)}};\n")); res.push_str(&format!("\t\tfld{field_id}.printf_debug();\n")); @@ -192,7 +192,7 @@ pub fn adt_impl_printf_debug(adt:&Adt,id:TyId,rust_gpu:bool)->String{ } res.push_str("\t\t}\n"); if rust_gpu{ - res.push_str("unsafe{printf!(\"}\")};\n"); + res.push_str("unsafe{debug_printf!(\"}\")};\n"); }else{ res.push_str("unsafe{printf(\"\\0}\".as_ptr() as *const c_char)};\n"); } @@ -203,18 +203,18 @@ pub fn adt_impl_printf_debug(adt:&Adt,id:TyId,rust_gpu:bool)->String{ else{ // Formats a struct let mut res = if rust_gpu{ - format!("impl PrintFDebug for {name}{{\n\tunsafe fn printf_debug(&self){{\n\tunsafe{{printf!(\"{name}{{\")}};",name = id.type_name()) + format!("impl PrintFDebug for {name}{{\n\tunsafe fn printf_debug(&self){{\n\tunsafe{{debug_printf!(\"{name}{{\")}};",name = id.type_name()) }else{format!("impl PrintFDebug for {name}{{\n\tunsafe fn printf_debug(&self){{\n\tunsafe{{printf(\"{name}{{\\0\".as_ptr() as *const c_char)}};",name = id.type_name())}; // Iterate trough fields to print values of fields of stuct for (field_id,_) in adt.variants[0].fields.iter().enumerate(){ if rust_gpu{ - res.push_str(&format!("\n\tprintf!(\"fld{field_id}:\");\n\tself.fld{field_id}.printf_debug();")); + res.push_str(&format!("\n\tdebug_printf!(\"fld{field_id}:\");\n\tself.fld{field_id}.printf_debug();")); }else{ res.push_str(&format!("\n\tprintf(\"fld{field_id}:\\0\".as_ptr() as *const c_char);\n\tself.fld{field_id}.printf_debug();")); } } if rust_gpu{ - res.push_str("\n\tunsafe{printf!(\"}\")};}\n}");} + res.push_str("\n\tunsafe{debug_printf!(\"}\")};}\n}");} else{ res.push_str("\n\tunsafe{printf(\"}\\0\".as_ptr() as *const c_char)};}\n}"); } From e47e1cc67af9bd06ce7e9b705069bdfa3c44432f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kostrubiec?= Date: Mon, 2 Dec 2024 20:52:24 +0100 Subject: [PATCH 19/20] Fixes to formatting code for 'rust-gpu' --- mir/src/syntax.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/mir/src/syntax.rs b/mir/src/syntax.rs index 8e8f349..19306b3 100644 --- a/mir/src/syntax.rs +++ b/mir/src/syntax.rs @@ -1151,7 +1151,7 @@ impl Program { "#; /// Implements printf based debuggig for primitive types. pub const RUSTGPU_PRINTF_DUMPER: &'static str = r#" - use core::ffi::{c_char, c_int,c_uint,c_long,c_ulong}; + use core::ffi::{c_char, c_int,c_uint,c_long}; trait PrintFDebug{ unsafe fn printf_debug(&self); } @@ -1207,7 +1207,7 @@ impl Program { }else{ debug_printf!( "%f", - *self as core::ffi::c_double, + *self as f32, ); } @@ -1220,7 +1220,7 @@ impl Program { }else{ debug_printf!( "%f", - *self as core::ffi::c_double, + *self as f32, ); } } @@ -1248,10 +1248,10 @@ impl Program { impl PrintFDebug for i64{ unsafe fn printf_debug(&self){ if *self < 0{ - debug_printf!("-%lu",*(-self) as c_ulong); + debug_printf!("-%lu",-self as u64); } else{ - debug_printf!("%lu",*self as c_ulong);} + debug_printf!("%lu",*self as u64);} } } impl PrintFDebug for u64{ @@ -1273,10 +1273,10 @@ impl Program { unsafe fn printf_debug(&self){ if *self < 0{ - debug_printf!("-%lu",*(-self) as c_ulong); + debug_printf!("-%lu",-self as u64); } else{ - debug_printf!("%lu",*self as c_ulong);} + debug_printf!("%lu",*self as u64);} } } From bdce6d4db94c7824890f16f72d87ff6db56285dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kostrubiec?= Date: Tue, 3 Dec 2024 22:56:10 +0100 Subject: [PATCH 20/20] Started working on supporting disabling fuzzing enums and 128 bit ints in rustlantis --- difftest/src/lib.rs | 5 +- generate/src/generation/intrinsics.rs | 4 +- generate/src/generation/mod.rs | 120 +++++++++++++++++--------- generate/src/literal.rs | 13 ++- generate/src/main.rs | 29 +++++-- generate/src/place_select.rs | 3 + generate/src/ty.rs | 60 +++++++++---- mir/src/lib.rs | 12 +-- mir/src/serialize.rs | 24 +++--- mir/src/syntax.rs | 4 +- mir/src/tyctxt.rs | 110 ++++++++++++++--------- 11 files changed, 255 insertions(+), 129 deletions(-) diff --git a/difftest/src/lib.rs b/difftest/src/lib.rs index c3d48d7..e1933d9 100644 --- a/difftest/src/lib.rs +++ b/difftest/src/lib.rs @@ -36,11 +36,12 @@ impl ExecResults { 'outer: for (&name, result) in map { for (class_result, names) in &mut eq_classes { // Put into an existing equivalence class - let eq = if let Ok(class_out) = class_result && let Ok(out) = result { + let eq = if let Ok(class_out) = class_result + && let Ok(out) = result + { class_out.stdout == out.stdout } else { result == class_result - }; if eq { names.insert(name); diff --git a/generate/src/generation/intrinsics.rs b/generate/src/generation/intrinsics.rs index f2b05e2..85dba65 100644 --- a/generate/src/generation/intrinsics.rs +++ b/generate/src/generation/intrinsics.rs @@ -127,7 +127,9 @@ impl CoreIntrinsic for Transmute { fn dest_type(&self, ty: TyId, tcx: &TyCtxt) -> bool { if ty.contains(tcx, |tcx, ty| match ty.kind(tcx) { // Tys with value validity contstraints - TyKind::Unit | TyKind::Bool | TyKind::Char | TyKind::RawPtr(..) | TyKind::Ref(..) => true, // TODO: pointer transmute + TyKind::Unit | TyKind::Bool | TyKind::Char | TyKind::RawPtr(..) | TyKind::Ref(..) => { + true + } // TODO: pointer transmute _ => false, }) { return false; diff --git a/generate/src/generation/mod.rs b/generate/src/generation/mod.rs index e6c37d3..900ed10 100644 --- a/generate/src/generation/mod.rs +++ b/generate/src/generation/mod.rs @@ -301,40 +301,80 @@ impl GenerationCtx { let target_ty = lhs.ty(self.current_decls(), &self.tcx); let source_tys = match target_ty.kind(&self.tcx) { // TODO: no int to ptr cast for now - TyKind::Int(..) | TyKind::Uint(..) => &[ - TyCtxt::ISIZE, - TyCtxt::I8, - TyCtxt::I16, - TyCtxt::I32, - TyCtxt::I64, - TyCtxt::I128, - TyCtxt::USIZE, - TyCtxt::U8, - TyCtxt::U16, - TyCtxt::U32, - TyCtxt::U64, - TyCtxt::U128, - TyCtxt::F32, - TyCtxt::F64, - TyCtxt::CHAR, - TyCtxt::BOOL, - ][..], - TyKind::Float(..) => &[ - TyCtxt::ISIZE, - TyCtxt::I8, - TyCtxt::I16, - TyCtxt::I32, - TyCtxt::I64, - TyCtxt::I128, - TyCtxt::USIZE, - TyCtxt::U8, - TyCtxt::U16, - TyCtxt::U32, - TyCtxt::U64, - TyCtxt::U128, - TyCtxt::F32, - TyCtxt::F64, - ][..], + TyKind::Int(..) | TyKind::Uint(..) => { + if self.tcx.no_128_bit_ints() { + &[ + TyCtxt::ISIZE, + TyCtxt::I8, + TyCtxt::I16, + TyCtxt::I32, + TyCtxt::I64, + TyCtxt::USIZE, + TyCtxt::U8, + TyCtxt::U16, + TyCtxt::U32, + TyCtxt::U64, + TyCtxt::F32, + TyCtxt::F64, + TyCtxt::CHAR, + TyCtxt::BOOL, + ][..] + } else { + &[ + TyCtxt::ISIZE, + TyCtxt::I8, + TyCtxt::I16, + TyCtxt::I32, + TyCtxt::I64, + TyCtxt::I128, + TyCtxt::USIZE, + TyCtxt::U8, + TyCtxt::U16, + TyCtxt::U32, + TyCtxt::U64, + TyCtxt::U128, + TyCtxt::F32, + TyCtxt::F64, + TyCtxt::CHAR, + TyCtxt::BOOL, + ][..] + } + } + TyKind::Float(..) => { + if self.tcx.no_128_bit_ints() { + &[ + TyCtxt::ISIZE, + TyCtxt::I8, + TyCtxt::I16, + TyCtxt::I32, + TyCtxt::I64, + TyCtxt::USIZE, + TyCtxt::U8, + TyCtxt::U16, + TyCtxt::U32, + TyCtxt::U64, + TyCtxt::F32, + TyCtxt::F64, + ][..] + } else { + &[ + TyCtxt::ISIZE, + TyCtxt::I8, + TyCtxt::I16, + TyCtxt::I32, + TyCtxt::I64, + TyCtxt::I128, + TyCtxt::USIZE, + TyCtxt::U8, + TyCtxt::U16, + TyCtxt::U32, + TyCtxt::U64, + TyCtxt::U128, + TyCtxt::F32, + TyCtxt::F64, + ][..] + } + } _ => &[][..], }; let rvalue = self.make_choice( @@ -991,7 +1031,10 @@ impl GenerationCtx { for vars in dumpped.chunks(Program::DUMPER_ARITY) { let new_bb = self.add_new_bb(); - let args = if matches!(self.program.var_dumper,VarDumper::StdVarDumper | VarDumper::PrintfVarDumper{..}){ + let args = if matches!( + self.program.var_dumper, + VarDumper::StdVarDumper | VarDumper::PrintfVarDumper { .. } + ) { let mut args = Vec::with_capacity(1 + Program::DUMPER_ARITY * 2); args.push(Operand::Constant( self.cursor.function.index().try_into().unwrap(), @@ -1210,10 +1253,9 @@ impl GenerationCtx { } } - pub fn new(seed: u64, debug_dump: VarDumper) -> Self { - + pub fn new(seed: u64, debug_dump: VarDumper, no_enums: bool,no_128_bit_ints:bool) -> Self { let rng = RefCell::new(Box::new(rand::rngs::SmallRng::seed_from_u64(seed))); - let tcx = Rc::new(seed_tys(&mut *rng.borrow_mut())); + let tcx = Rc::new(seed_tys(&mut *rng.borrow_mut(), no_enums,no_128_bit_ints)); let ty_weights = TySelect::new(&tcx); // TODO: don't zero-initialize current_function and current_bb Self { @@ -1267,7 +1309,7 @@ impl GenerationCtx { let arg_tys: Vec = self .tcx .indices() - .filter(|ty| ::is_literalble(*ty, &self.tcx)) + .filter(|ty| ::is_literalble(*ty, &self.tcx) ) .choose_multiple(&mut *self.rng.borrow_mut(), args_count); let arg_literals: Vec = arg_tys .iter() diff --git a/generate/src/literal.rs b/generate/src/literal.rs index 640c5a0..bd28cca 100644 --- a/generate/src/literal.rs +++ b/generate/src/literal.rs @@ -32,10 +32,17 @@ impl Distribution for Sombrero { pub trait GenLiteral: Rng { fn is_literalble(ty: TyId, tcx: &TyCtxt) -> bool { - match ty.kind(tcx) { + let res = match ty.kind(tcx) { TyKind::Unit => false, - _ => ty.is_scalar(tcx), - } + _ => { + if tcx.no_128_bit_ints() && (ty == TyCtxt::U128 || ty == TyCtxt::I128) { + false + } else { + ty.is_scalar(tcx) + } + } + }; + res } fn gen_literal(&mut self, ty: TyId, tcx: &TyCtxt) -> Option { let lit: Literal = match ty.kind(tcx) { diff --git a/generate/src/main.rs b/generate/src/main.rs index ba4dd10..f27c7db 100644 --- a/generate/src/main.rs +++ b/generate/src/main.rs @@ -10,8 +10,8 @@ mod generation; mod literal; mod mem; -mod place_select; mod pgraph; +mod place_select; mod ty; use mir::VarDumper; use std::time::Instant; @@ -19,7 +19,6 @@ use std::time::Instant; use clap::{arg, command, value_parser, Arg}; use log::{debug, info}; - use crate::generation::GenerationCtx; fn main() { @@ -29,7 +28,10 @@ fn main() { arg!(-d --debug "generate a program where values are printed instead of hashed (slow)"), arg!(-p --printf_debug "generate a program where values are printed using the C 'printf' function instead of hashed (slow)"), - arg!(-g --rust_gpu "generate a program where values are printed using the C 'printf' function instead of hashed (slow)"), + arg!(--rust_gpu "generate a program where values are printed using the C 'printf' function instead of hashed (slow)"), + arg!(--no_enums "generate a program without enums"), + arg!(--no_128_bit_ints "generate a program without 128 bit ints"), + Arg::new("call-syntax") .long("call-syntax") .value_parser(["v1", "v2", "v3", "v4"]) @@ -44,8 +46,23 @@ fn main() { .get_one::("seed") .expect("need an integer as seed"); let debug_dump = matches.get_one::("debug").copied().unwrap_or(false); - let rust_gpu = matches.get_one::("rust_gpu").copied().unwrap_or(false); - let printf_dump = matches.get_one::("printf_debug").copied().unwrap_or(false) | rust_gpu; + let rust_gpu = matches + .get_one::("rust_gpu") + .copied() + .unwrap_or(false); + let no_enums = matches + .get_one::("no_enums") + .copied() + .unwrap_or(false); + let no_128_bit_ints = matches + .get_one::("no_128_bit_ints") + .copied() + .unwrap_or(false); + let printf_dump = matches + .get_one::("printf_debug") + .copied() + .unwrap_or(false) + | rust_gpu; let dumper = match (debug_dump,printf_dump){ (false,false)=>VarDumper::HashDumper, (true,false)=>VarDumper::StdVarDumper, @@ -55,7 +72,7 @@ fn main() { info!("Generating a program with seed {seed}"); let call_syntax = matches.get_one::("call-syntax").unwrap(); - let genctxt = GenerationCtx::new(seed, dumper); + let genctxt = GenerationCtx::new(seed, dumper, no_enums,no_128_bit_ints); let time = Instant::now(); let (program, tcx) = genctxt.generate(); println!("{}", program.serialize(&tcx, call_syntax.as_str().into())); diff --git a/generate/src/place_select.rs b/generate/src/place_select.rs index 0d16822..1fa5ac3 100644 --- a/generate/src/place_select.rs +++ b/generate/src/place_select.rs @@ -159,6 +159,7 @@ impl PlaceSelector { } fn into_iter_path(self, pt: &PlaceGraph) -> impl Iterator + Clone + '_ { + let exclusion_indicies: Vec = self .exclusions .iter() @@ -289,10 +290,12 @@ impl PlaceSelector { pub fn into_weighted(self, pt: &PlaceGraph) -> Option<(Vec, WeightedIndex)> { let usage = self.usage; let tcx = self.tcx.clone(); + let (places, weights): (Vec, Vec) = self.into_iter_path(pt) .map(|ppath| { let place = ppath.target_index(); + let mut weight = match usage { PlaceUsage::Argument => { let mut weight = 1; diff --git a/generate/src/ty.rs b/generate/src/ty.rs index 9420fd5..958771c 100644 --- a/generate/src/ty.rs +++ b/generate/src/ty.rs @@ -65,9 +65,7 @@ impl TySelect { TyKind::Int(..) => Some(p_ints / TyKind::INTS.len() as f32), TyKind::Uint(..) => Some(p_ints / TyKind::INTS.len() as f32), TyKind::Float(..) => Some(p_floats / TyKind::FLOATS.len() as f32), - TyKind::RawPtr(..) | TyKind::Ref(..) => { - Some(p_pointers / num_ptrs as f32) - } + TyKind::RawPtr(..) | TyKind::Ref(..) => Some(p_pointers / num_ptrs as f32), _ => None, }; if let Some(rate) = p { @@ -96,8 +94,8 @@ impl TySelect { .unwrap(); } trace!("Typing context with weights:\n{s}"); - // FractalFir: serialization requires info about which dumper(printf-based one or not) is used. I pass `StdVarDumper` here to preserve - // previous behaviour. + // FractalFir: serialization requires info about which dumper(printf-based one or not) is used. I pass `StdVarDumper` here to preserve + // previous behaviour. trace!("{}", tcx.serialize(mir::VarDumper::StdVarDumper)); } @@ -106,9 +104,15 @@ impl TySelect { } pub fn choose_ty(&self, rng: &mut impl Rng, tcx: &TyCtxt) -> TyId { - tcx.indices() + let res = tcx.indices() .nth(self.weights.sample(rng)) - .expect("tyctxt isn't empty") + .expect("tyctxt isn't empty"); + if tcx.no_128_bit_ints() && (res == TyCtxt::I128 || res == TyCtxt::U128){ + TyCtxt::U64 + }else{ + res + } + } } @@ -120,7 +124,11 @@ fn new_composite(tcx: &mut TyCtxt, rng: &mut impl Rng) { (0..length) .map(|_| { tcx.indices() - .filter(|ty| *ty != TyCtxt::UNIT) + .filter(|ty| { + *ty != TyCtxt::UNIT + && (!tcx.no_128_bit_ints() + || !(*ty == TyCtxt::U128 || *ty == TyCtxt::I128)) + }) .choose(rng) .unwrap() }) @@ -128,7 +136,10 @@ fn new_composite(tcx: &mut TyCtxt, rng: &mut impl Rng) { }), 1 => TyKind::RawPtr( tcx.indices() - .filter(|ty| *ty != TyCtxt::UNIT) + .filter(|ty| { + *ty != TyCtxt::UNIT + && (!tcx.no_128_bit_ints() || !(*ty == TyCtxt::U128 || *ty == TyCtxt::I128)) + }) .choose(rng) .unwrap(), if rng.gen_bool(0.5) { @@ -139,7 +150,10 @@ fn new_composite(tcx: &mut TyCtxt, rng: &mut impl Rng) { ), 2 => TyKind::Ref( tcx.indices() - .filter(|ty| *ty != TyCtxt::UNIT) + .filter(|ty| { + *ty != TyCtxt::UNIT + && (!tcx.no_128_bit_ints() || !(*ty == TyCtxt::U128 || *ty == TyCtxt::I128)) + }) .choose(rng) .unwrap(), if rng.gen_bool(0.5) { @@ -150,7 +164,12 @@ fn new_composite(tcx: &mut TyCtxt, rng: &mut impl Rng) { ), 3 => TyKind::Array( tcx.iter_enumerated() - .filter_map(|(ty, kind)| (ty != TyCtxt::UNIT && kind.is_scalar()).then_some(ty)) + .filter_map(|(ty, kind)| { + (ty != TyCtxt::UNIT + && kind.is_scalar() + && (!tcx.no_128_bit_ints() || !(ty == TyCtxt::U128 || ty == TyCtxt::I128))) + .then_some(ty) + }) .choose(rng) .unwrap(), rng.gen_range(1..=ARRAY_MAX_LEN), @@ -164,13 +183,17 @@ fn new_composite(tcx: &mut TyCtxt, rng: &mut impl Rng) { fn new_adt(tcx: &mut TyCtxt, rng: &mut impl Rng) { // TODO: recursive types - let variant_count = rng.gen_range(1..=ADT_MAX_VARIANTS); + let variant_count = if tcx.no_enums() { + 1 + } else { + rng.gen_range(1..=ADT_MAX_VARIANTS) + }; let variants = (0..variant_count).map(|_| { let field_count = rng.gen_range(1..=STRUCT_MAX_FIELDS); let field_tys = tcx .indices() - .filter(|ty| *ty != TyCtxt::UNIT && /* https://github.com/rust-lang/rust/issues/119940 */ !ty.contains(&tcx, |tcx, ty| ty.is_ref(tcx))) + .filter(|ty| *ty != TyCtxt::UNIT && /* https://github.com/rust-lang/rust/issues/119940 */ !ty.contains(tcx, |tcx, ty| ty.is_ref(tcx)) && (!tcx.no_128_bit_ints() || !(*ty == TyCtxt::U128 || *ty == TyCtxt::I128))) .choose_multiple(rng, field_count); VariantDef { fields: IndexVec::from_iter(field_tys.into_iter()), @@ -191,9 +214,9 @@ fn new_adt(tcx: &mut TyCtxt, rng: &mut impl Rng) { tcx.push_adt(adt, meta); } -pub fn seed_tys(rng: &mut R) -> TyCtxt { +pub fn seed_tys(rng: &mut R, no_enums: bool,no_128_bit_ints:bool) -> TyCtxt { // Seed with primitives - let mut tcx: TyCtxt = TyCtxt::from_primitives(); + let mut tcx: TyCtxt = TyCtxt::from_primitives(no_enums,no_128_bit_ints); #[derive(Clone, Copy)] enum Kind { @@ -227,7 +250,12 @@ mod tests { #[test] fn tys_unique() { let mut rng = rand::rngs::SmallRng::seed_from_u64(0); - let tcx = seed_tys(&mut rng); + let tcx = seed_tys(&mut rng, false); + let set: HashSet = tcx.indices().collect(); + assert!(set.len() == tcx.len()); + // Test without enums + let mut rng = rand::rngs::SmallRng::seed_from_u64(0); + let tcx = seed_tys(&mut rng, true); let set: HashSet = tcx.indices().collect(); assert!(set.len() == tcx.len()) } diff --git a/mir/src/lib.rs b/mir/src/lib.rs index 3c7fd8b..006c790 100644 --- a/mir/src/lib.rs +++ b/mir/src/lib.rs @@ -4,13 +4,13 @@ pub mod serialize; pub mod syntax; pub mod tyctxt; -pub const ENABLE_PRINTF_DEBUG:bool = true; -#[derive(Clone,Copy,PartialEq, Eq)] -pub enum VarDumper{ +pub const ENABLE_PRINTF_DEBUG: bool = true; +#[derive(Clone, Copy, PartialEq, Eq)] +pub enum VarDumper { /// Print variable hashes HashDumper, - /// Print variables using standard rust formatting + /// Print variables using standard rust formatting StdVarDumper, /// Print variables using the c `printf` function. If `rust_gpu` is true, then use the `debug_printf!()` rust-gpu macro instead of `printf` - PrintfVarDumper{rust_gpu:bool}, -} \ No newline at end of file + PrintfVarDumper { rust_gpu: bool }, +} diff --git a/mir/src/serialize.rs b/mir/src/serialize.rs index fb72329..b865518 100644 --- a/mir/src/serialize.rs +++ b/mir/src/serialize.rs @@ -368,17 +368,17 @@ impl Body { impl Program { pub fn serialize(&self, tcx: &TyCtxt, call_syntax: CallSynatx) -> String { - let mut program =match self.var_dumper{ - VarDumper::PrintfVarDumper{rust_gpu:true}=>Program::NOSTD_HEADER.to_string(), - _=> Program::HEADER.to_string(), + let mut program = match self.var_dumper { + VarDumper::PrintfVarDumper { rust_gpu: true } => Program::NOSTD_HEADER.to_string(), + _ => Program::HEADER.to_string(), }; - program += match self.var_dumper{ - VarDumper::HashDumper=>Program::DUMPER, - VarDumper::StdVarDumper=>Program::DEBUG_DUMPER, - VarDumper::PrintfVarDumper{rust_gpu:false}=>Program::PRINTF_DUMPER, - VarDumper::PrintfVarDumper{rust_gpu:true}=>Program::RUSTGPU_PRINTF_DUMPER, + program += match self.var_dumper { + VarDumper::HashDumper => Program::DUMPER, + VarDumper::StdVarDumper => Program::DEBUG_DUMPER, + VarDumper::PrintfVarDumper { rust_gpu: false } => Program::PRINTF_DUMPER, + VarDumper::PrintfVarDumper { rust_gpu: true } => Program::RUSTGPU_PRINTF_DUMPER, }; - if let VarDumper::PrintfVarDumper { rust_gpu:true } = self.var_dumper { + if let VarDumper::PrintfVarDumper { rust_gpu: true } = self.var_dumper { program += "use spirv_std::{spirv,macros::debug_printf};\n"; } program.extend(self.functions.iter_enumerated().map(|(idx, body)| { @@ -428,7 +428,7 @@ impl Program { } "# }; - if let VarDumper::PrintfVarDumper { rust_gpu:true } = self.var_dumper { + if let VarDumper::PrintfVarDumper { rust_gpu: true } = self.var_dumper { program.push_str(&format!( "#[spirv(compute(threads(1)))] pub fn main() {{ @@ -436,7 +436,7 @@ impl Program { {hash_printer} }}" )); - } else{ + } else { program.push_str(&format!( "pub fn main() {{ {first_fn}({arg_list}); @@ -444,7 +444,7 @@ impl Program { }}" )); } - + program } } diff --git a/mir/src/syntax.rs b/mir/src/syntax.rs index 19306b3..0cd265a 100644 --- a/mir/src/syntax.rs +++ b/mir/src/syntax.rs @@ -1149,8 +1149,8 @@ impl Program { } } "#; - /// Implements printf based debuggig for primitive types. - pub const RUSTGPU_PRINTF_DUMPER: &'static str = r#" + /// Implements printf based debuggig for primitive types. + pub const RUSTGPU_PRINTF_DUMPER: &'static str = r#" use core::ffi::{c_char, c_int,c_uint,c_long}; trait PrintFDebug{ unsafe fn printf_debug(&self); diff --git a/mir/src/tyctxt.rs b/mir/src/tyctxt.rs index 560e213..63ed71f 100644 --- a/mir/src/tyctxt.rs +++ b/mir/src/tyctxt.rs @@ -3,7 +3,9 @@ use std::{collections::HashMap, slice}; use index_vec::IndexVec; use crate::{ - serialize::Serialize, syntax::{Adt, TyId, TyKind}, VarDumper + serialize::Serialize, + syntax::{Adt, TyId, TyKind}, + VarDumper, }; #[derive(Debug, Clone, Copy)] @@ -31,6 +33,8 @@ impl AdtMeta { pub struct TyCtxt { tys: IndexVec, adt_meta: HashMap, + no_enums: bool, + no_128_bit_ints: bool, } impl TyCtxt { @@ -52,7 +56,7 @@ impl TyCtxt { pub const F32: TyId = TyId::from_usize_unchecked(15); pub const F64: TyId = TyId::from_usize_unchecked(16); - pub fn from_primitives() -> Self { + pub fn from_primitives(no_enums: bool,no_128_bit_ints:bool) -> Self { let primitives: [TyKind; 17] = [ TyKind::Unit, TyKind::Bool, @@ -76,6 +80,8 @@ impl TyCtxt { Self { tys, adt_meta: HashMap::new(), + no_enums, + no_128_bit_ints, } } @@ -114,16 +120,18 @@ impl TyCtxt { self.tys.len() } - pub fn serialize(&self,dumper:VarDumper) -> String { + pub fn serialize(&self, dumper: VarDumper) -> String { let mut str = String::new(); for (id, adt) in self.tys.iter_enumerated().filter(|(_, kind)| kind.is_adt()) { let TyKind::Adt(adt) = adt else { panic!("not an adt"); }; // `Debug` derive is ommited for printf-based dumping. An implemntation of the PrintFDebug trait is emmited instead. - str += &match dumper{ - VarDumper::HashDumper | VarDumper::StdVarDumper => self.adt_meta[&id].derive_attrs(), - VarDumper::PrintfVarDumper{rust_gpu} => adt_impl_printf_debug(adt,id,rust_gpu), + str += &match dumper { + VarDumper::HashDumper | VarDumper::StdVarDumper => { + self.adt_meta[&id].derive_attrs() + } + VarDumper::PrintfVarDumper { rust_gpu } => adt_impl_printf_debug(adt, id, rust_gpu), }; if adt.is_enum() { let variants: String = adt @@ -146,81 +154,99 @@ impl TyCtxt { } str } + + pub fn no_enums(&self) -> bool { + self.no_enums + } + + pub fn no_128_bit_ints(&self) -> bool { + self.no_128_bit_ints + } } /// Implements the PrintFDebug trait for an ADT. /// This trait is used to dump variables using `printf` -pub fn adt_impl_printf_debug(adt:&Adt,id:TyId,rust_gpu:bool)->String{ +pub fn adt_impl_printf_debug(adt: &Adt, id: TyId, rust_gpu: bool) -> String { let res = if adt.is_enum() { // Formats an enum let name = id.type_name(); let mut res = format!("impl PrintFDebug for {name}{{\n\tunsafe fn printf_debug(&self){{"); - if rust_gpu{ - res.push_str(&format!("unsafe{{debug_printf!(\"{name}::\")}};")); - }else{ - res.push_str(&format!("unsafe{{printf(\"{name}::\\0\".as_ptr() as *const c_char)}};")); + if rust_gpu { + res.push_str(&format!("unsafe{{debug_printf!(\"{name}::\")}};")); + } else { + res.push_str(&format!( + "unsafe{{printf(\"{name}::\\0\".as_ptr() as *const c_char)}};" + )); } - + res.push_str("match self{\n"); // Iterate through variants cratete a match statement - for (variant_idx,variant) in adt.variants.iter().enumerate(){ + for (variant_idx, variant) in adt.variants.iter().enumerate() { res.push_str(&format!("\tSelf::Variant{variant_idx}{{",)); // Iterate trough fields to generate match patterns - for (field_id,_) in variant.fields.iter().enumerate(){ + for (field_id, _) in variant.fields.iter().enumerate() { res.push_str(&format!("fld{field_id},")); } res.push_str("}=>{\n"); - if rust_gpu{ - res.push_str(&format!("unsafe{{debug_printf!(\"Variant{variant_idx}{{\")}};\n")); - }else{ - res.push_str(&format!("unsafe{{printf(\"Variant{variant_idx}{{\\0\".as_ptr() as *const c_char)}};\n")); + if rust_gpu { + res.push_str(&format!( + "unsafe{{debug_printf!(\"Variant{variant_idx}{{\")}};\n" + )); + } else { + res.push_str(&format!( + "unsafe{{printf(\"Variant{variant_idx}{{\\0\".as_ptr() as *const c_char)}};\n" + )); } - + // Iterate trough fields to print values of fields of variant - for (field_id,_) in variant.fields.iter().enumerate(){ - if rust_gpu{ - res.push_str(&format!("\t\tunsafe{{debug_printf!(\"fld{field_id}:\")}};\n")); + for (field_id, _) in variant.fields.iter().enumerate() { + if rust_gpu { + res.push_str(&format!( + "\t\tunsafe{{debug_printf!(\"fld{field_id}:\")}};\n" + )); res.push_str(&format!("\t\tfld{field_id}.printf_debug();\n")); res.push_str("unsafe{debug_printf!(\",\")};\n"); - }else{ - res.push_str(&format!("\t\tunsafe{{printf(\"fld{field_id}:\\0\".as_ptr() as *const c_char)}};\n")); + } else { + res.push_str(&format!( + "\t\tunsafe{{printf(\"fld{field_id}:\\0\".as_ptr() as *const c_char)}};\n" + )); res.push_str(&format!("\t\tfld{field_id}.printf_debug();\n")); res.push_str("unsafe{printf(\",\\0\".as_ptr() as *const c_char)};\n"); } - } res.push_str("},\n") } res.push_str("\t\t}\n"); - if rust_gpu{ + if rust_gpu { res.push_str("unsafe{debug_printf!(\"}\")};\n"); - }else{ + } else { res.push_str("unsafe{printf(\"\\0}\".as_ptr() as *const c_char)};\n"); } - + res.push_str("\t}\n}"); res - } - else{ + } else { // Formats a struct - let mut res = if rust_gpu{ + let mut res = if rust_gpu { format!("impl PrintFDebug for {name}{{\n\tunsafe fn printf_debug(&self){{\n\tunsafe{{debug_printf!(\"{name}{{\")}};",name = id.type_name()) - }else{format!("impl PrintFDebug for {name}{{\n\tunsafe fn printf_debug(&self){{\n\tunsafe{{printf(\"{name}{{\\0\".as_ptr() as *const c_char)}};",name = id.type_name())}; + } else { + format!("impl PrintFDebug for {name}{{\n\tunsafe fn printf_debug(&self){{\n\tunsafe{{printf(\"{name}{{\\0\".as_ptr() as *const c_char)}};",name = id.type_name()) + }; // Iterate trough fields to print values of fields of stuct - for (field_id,_) in adt.variants[0].fields.iter().enumerate(){ - if rust_gpu{ - res.push_str(&format!("\n\tdebug_printf!(\"fld{field_id}:\");\n\tself.fld{field_id}.printf_debug();")); - }else{ + for (field_id, _) in adt.variants[0].fields.iter().enumerate() { + if rust_gpu { + res.push_str(&format!( + "\n\tdebug_printf!(\"fld{field_id}:\");\n\tself.fld{field_id}.printf_debug();" + )); + } else { res.push_str(&format!("\n\tprintf(\"fld{field_id}:\\0\".as_ptr() as *const c_char);\n\tself.fld{field_id}.printf_debug();")); } } - if rust_gpu{ - res.push_str("\n\tunsafe{debug_printf!(\"}\")};}\n}");} - else{ - res.push_str("\n\tunsafe{printf(\"}\\0\".as_ptr() as *const c_char)};}\n}"); + if rust_gpu { + res.push_str("\n\tunsafe{debug_printf!(\"}\")};}\n}"); + } else { + res.push_str("\n\tunsafe{printf(\"}\\0\".as_ptr() as *const c_char)};}\n}"); } res }; format!("{res}\n#[derive(Copy,Clone)]") - } -