diff --git a/cranelift/isle/isle_examples/test_main.rs b/cranelift/isle/isle_examples/test_main.rs index 92cfdf2c0b..5bec55a798 100644 --- a/cranelift/isle/isle_examples/test_main.rs +++ b/cranelift/isle/isle_examples/test_main.rs @@ -1,8 +1,12 @@ +mod test; -pub fn get_input(ctx: &mut C, x: u32) -> Option<(test::A,)> { - None +struct Context; +impl test::Context for Context { + fn get_input(&mut self, x: u32) -> Option<(test::A,)> { + Some((test::A::A1 { x: x + 1 },)) + } } -fn main() {} - -mod test; +fn main() { + test::constructor_Lower(&mut Context, &test::A::A1 { x: 42 }); +} diff --git a/cranelift/isle/src/codegen.rs b/cranelift/isle/src/codegen.rs index 12839d819d..4c7fc04a93 100644 --- a/cranelift/isle/src/codegen.rs +++ b/cranelift/isle/src/codegen.rs @@ -559,6 +559,7 @@ impl<'a> Codegen<'a> { let mut code = String::new(); self.generate_header(&mut code)?; + self.generate_ctx_trait(&mut code)?; self.generate_internal_types(&mut code)?; self.generate_internal_term_constructors(&mut code)?; self.generate_internal_term_extractors(&mut code)?; @@ -576,11 +577,105 @@ impl<'a> Codegen<'a> { for file in &self.typeenv.filenames { writeln!(code, "// - {}", file)?; } + writeln!( code, - "\nuse super::*; // Pulls in all external types and ctors/etors" + "\n#![allow(dead_code, unreachable_code, unused_imports, unused_variables, non_snake_case)]" )?; + writeln!(code, "\nuse super::*; // Pulls in all external types.")?; + + Ok(()) + } + + fn generate_ctx_trait(&self, code: &mut dyn Write) -> Result<(), Error> { + writeln!(code, "")?; + writeln!( + code, + "/// Context during lowering: an implementation of this trait" + )?; + writeln!( + code, + "/// must be provided with all external constructors and extractors." + )?; + writeln!( + code, + "/// A mutable borrow is passed along through all lowering logic." + )?; + writeln!(code, "pub trait Context {{")?; + for term in &self.termenv.terms { + if let &TermKind::Regular { + extractor, + constructor, + .. + } = &term.kind + { + if let Some((etor_name, infallible)) = extractor { + let etor_name = &self.typeenv.syms[etor_name.index()]; + let arg_is_prim = match &self.typeenv.types[term.ret_ty.index()] { + &Type::Primitive(..) => true, + _ => false, + }; + let arg = format!( + "arg0: {}", + self.type_name( + term.ret_ty, + /* by_ref = */ if arg_is_prim { None } else { Some("&") } + ), + ); + let ret_tuple_tys = term + .arg_tys + .iter() + .map(|ty| { + self.type_name(*ty, /* by_ref = */ None) + }) + .collect::>(); + if infallible { + writeln!( + code, + " fn {}(&mut self, {}) -> ({},);", + etor_name, + arg, + ret_tuple_tys.join(", ") + )?; + } else { + writeln!( + code, + " fn {}(&mut self, {}) -> Option<({},)>;", + etor_name, + arg, + ret_tuple_tys.join(", ") + )?; + } + } + + if let Some(ctor_name) = constructor { + let ctor_name = &self.typeenv.syms[ctor_name.index()]; + let args = term + .arg_tys + .iter() + .enumerate() + .map(|(i, &arg_ty)| { + format!( + "arg{}: {}", + i, + self.type_name(arg_ty, /* by_ref = */ Some("&")) + ) + }) + .collect::>(); + let ret = self.type_name(term.ret_ty, /* by_ref = */ None); + writeln!( + code, + "fn {}(&mut self, {}) -> Option<{}>;", + ctor_name, + args.join(", "), + ret, + )?; + } + } + } + writeln!(code, "}}")?; + Ok(()) } @@ -628,7 +723,7 @@ impl<'a> Codegen<'a> { &TermKind::Regular { constructor: Some(sym), .. - } => self.typeenv.syms[sym.index()].clone(), + } => format!("C::{}", self.typeenv.syms[sym.index()]), &TermKind::Regular { constructor: None, .. } => { @@ -644,7 +739,7 @@ impl<'a> Codegen<'a> { &TermKind::Regular { extractor: Some((sym, infallible)), .. - } => (self.typeenv.syms[sym.index()].clone(), infallible), + } => (format!("C::{}", self.typeenv.syms[sym.index()]), infallible), &TermKind::Regular { extractor: None, .. } => ( @@ -729,7 +824,7 @@ impl<'a> Codegen<'a> { )?; writeln!( code, - "fn {}(ctx: &mut C, {}) -> Option<{}> {{", + "pub fn {}(ctx: &mut C, {}) -> Option<{}> {{", func_name, args.join(", "), self.type_name(termdata.ret_ty, /* by_ref = */ None) @@ -788,7 +883,7 @@ impl<'a> Codegen<'a> { )?; writeln!( code, - "fn {}(ctx: &mut C, {}) -> Option<({},)> {{", + "pub fn {}(ctx: &mut C, {}) -> Option<({},)> {{", func_name, arg, ret_tuple_tys.join(", "), @@ -1114,7 +1209,7 @@ impl<'a> Codegen<'a> { // chain of if-lets. let mut edges = edges.clone(); edges.sort_by(|e1, e2| (-e1.range.0, &e1.symbol).cmp(&(-e2.range.0, &e2.symbol))); - + let mut i = 0; while i < edges.len() { let mut last = i;