diff --git a/cranelift/isle/isle/src/codegen.rs b/cranelift/isle/isle/src/codegen.rs index f518fd12b0..cc5dda9994 100644 --- a/cranelift/isle/isle/src/codegen.rs +++ b/cranelift/isle/isle/src/codegen.rs @@ -1,8 +1,8 @@ //! Generate Rust code from a series of Sequences. use crate::ir::{lower_rule, ExprInst, ExprSequence, InstId, PatternInst, PatternSequence, Value}; +use crate::sema::ExternalSig; use crate::sema::{RuleId, TermEnv, TermId, Type, TypeEnv, TypeId, Variant}; -use crate::{error::Error, sema::ExternalSig}; use std::collections::{HashMap, HashSet}; use std::fmt::Write; @@ -506,60 +506,56 @@ struct BodyContext { } impl<'a> Codegen<'a> { - pub fn compile(typeenv: &'a TypeEnv, termenv: &'a TermEnv) -> Result, Error> { + pub fn compile(typeenv: &'a TypeEnv, termenv: &'a TermEnv) -> Codegen<'a> { let mut builder = TermFunctionsBuilder::new(typeenv, termenv); builder.build(); log::trace!("builder: {:?}", builder); let functions_by_term = builder.finalize(); - Ok(Codegen { + Codegen { typeenv, termenv, functions_by_term, - }) + } } - pub fn generate_rust(&self) -> Result { + pub fn generate_rust(&self) -> String { 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_header(&mut code); + self.generate_ctx_trait(&mut code); + self.generate_internal_types(&mut code); + self.generate_internal_term_constructors(&mut code); - Ok(code) + code } - fn generate_header(&self, code: &mut dyn Write) -> Result<(), Error> { - writeln!(code, "// GENERATED BY ISLE. DO NOT EDIT!")?; - writeln!(code, "//")?; + fn generate_header(&self, code: &mut String) { + writeln!(code, "// GENERATED BY ISLE. DO NOT EDIT!").unwrap(); + writeln!(code, "//").unwrap(); writeln!( code, "// Generated automatically from the instruction-selection DSL code in:", - )?; + ) + .unwrap(); for file in &self.typeenv.filenames { - writeln!(code, "// - {}", file)?; + writeln!(code, "// - {}", file).unwrap(); } writeln!( code, "\n#![allow(dead_code, unreachable_code, unreachable_patterns)]" - )?; + ) + .unwrap(); writeln!( code, "#![allow(unused_imports, unused_variables, non_snake_case)]" - )?; + ) + .unwrap(); - writeln!(code, "\nuse super::*; // Pulls in all external types.")?; - - Ok(()) + writeln!(code, "\nuse super::*; // Pulls in all external types.").unwrap(); } - fn generate_trait_sig( - &self, - code: &mut dyn Write, - indent: &str, - sig: &ExternalSig, - ) -> Result<(), Error> { + fn generate_trait_sig(&self, code: &mut String, indent: &str, sig: &ExternalSig) { writeln!( code, "{}fn {}(&mut self, {}) -> {}({},){};", @@ -578,37 +574,38 @@ impl<'a> Codegen<'a> { .collect::>() .join(", "), if sig.infallible { "" } else { ">" }, - )?; - Ok(()) + ) + .unwrap(); } - fn generate_ctx_trait(&self, code: &mut dyn Write) -> Result<(), Error> { - writeln!(code, "")?; + fn generate_ctx_trait(&self, code: &mut String) { + writeln!(code, "").unwrap(); writeln!( code, "/// Context during lowering: an implementation of this trait" - )?; + ) + .unwrap(); writeln!( code, "/// must be provided with all external constructors and extractors." - )?; + ) + .unwrap(); writeln!( code, "/// A mutable borrow is passed along through all lowering logic." - )?; - writeln!(code, "pub trait Context {{")?; + ) + .unwrap(); + writeln!(code, "pub trait Context {{").unwrap(); for term in &self.termenv.terms { if term.is_external() { let ext_sig = term.to_sig(self.typeenv).unwrap(); - self.generate_trait_sig(code, " ", &ext_sig)?; + self.generate_trait_sig(code, " ", &ext_sig); } } - writeln!(code, "}}")?; - - Ok(()) + writeln!(code, "}}").unwrap(); } - fn generate_internal_types(&self, code: &mut dyn Write) -> Result<(), Error> { + fn generate_internal_types(&self, code: &mut String) { for ty in &self.typeenv.types { match ty { &Type::Enum { @@ -624,30 +621,30 @@ impl<'a> Codegen<'a> { "\n/// Internal type {}: defined at {}.", name, pos.pretty_print_line(&self.typeenv.filenames[..]) - )?; - writeln!(code, "#[derive(Clone, Debug)]")?; - writeln!(code, "pub enum {} {{", name)?; + ) + .unwrap(); + writeln!(code, "#[derive(Clone, Debug)]").unwrap(); + writeln!(code, "pub enum {} {{", name).unwrap(); for variant in variants { let name = &self.typeenv.syms[variant.name.index()]; if variant.fields.is_empty() { - writeln!(code, " {},", name)?; + writeln!(code, " {},", name).unwrap(); } else { - writeln!(code, " {} {{", name)?; + writeln!(code, " {} {{", name).unwrap(); for field in &variant.fields { let name = &self.typeenv.syms[field.name.index()]; let ty_name = self.typeenv.types[field.ty.index()].name(&self.typeenv); - writeln!(code, " {}: {},", name, ty_name)?; + writeln!(code, " {}: {},", name, ty_name).unwrap(); } - writeln!(code, " }},")?; + writeln!(code, " }},").unwrap(); } } - writeln!(code, "}}")?; + writeln!(code, "}}").unwrap(); } _ => {} } } - Ok(()) } fn type_name(&self, typeid: TypeId, by_ref: bool) -> String { @@ -718,7 +715,7 @@ impl<'a> Codegen<'a> { } } - fn generate_internal_term_constructors(&self, code: &mut dyn Write) -> Result<(), Error> { + fn generate_internal_term_constructors(&self, code: &mut String) { for (&termid, trie) in &self.functions_by_term { let termdata = &self.termenv.terms[termid.index()]; @@ -744,35 +741,35 @@ impl<'a> Codegen<'a> { code, "\n// Generated as internal constructor for term {}.", self.typeenv.syms[termdata.name.index()], - )?; + ) + .unwrap(); writeln!( code, "pub fn {}(ctx: &mut C, {}) -> Option<{}> {{", sig.func_name, args, ret, - )?; + ) + .unwrap(); let mut body_ctx: BodyContext = Default::default(); let returned = - self.generate_body(code, /* depth = */ 0, trie, " ", &mut body_ctx)?; + self.generate_body(code, /* depth = */ 0, trie, " ", &mut body_ctx); if !returned { - writeln!(code, " return None;")?; + writeln!(code, " return None;").unwrap(); } - writeln!(code, "}}")?; + writeln!(code, "}}").unwrap(); } - - Ok(()) } fn generate_expr_inst( &self, - code: &mut dyn Write, + code: &mut String, id: InstId, inst: &ExprInst, indent: &str, ctx: &mut BodyContext, returns: &mut Vec<(usize, String)>, - ) -> Result<(), Error> { + ) { log::trace!("generate_expr_inst: {:?}", inst); match inst { &ExprInst::ConstInt { ty, val } => { @@ -790,7 +787,8 @@ impl<'a> Codegen<'a> { name, ty_name, self.const_int(val, ty) - )?; + ) + .unwrap(); } &ExprInst::ConstPrim { ty, val } => { let value = Value::Expr { @@ -807,7 +805,8 @@ impl<'a> Codegen<'a> { name, ty_name, self.typeenv.syms[val.index()], - )?; + ) + .unwrap(); } &ExprInst::CreateVariant { ref inputs, @@ -840,17 +839,19 @@ impl<'a> Codegen<'a> { code, "{}let {} = {};", indent, outputname, full_variant_name - )?; + ) + .unwrap(); } else { writeln!( code, "{}let {} = {} {{", indent, outputname, full_variant_name - )?; + ) + .unwrap(); for input_field in input_fields { - writeln!(code, "{} {},", indent, input_field)?; + writeln!(code, "{} {},", indent, input_field).unwrap(); } - writeln!(code, "{}}};", indent)?; + writeln!(code, "{}}};", indent).unwrap(); } self.define_val(&output, ctx, /* is_ref = */ false, ty); } @@ -883,7 +884,8 @@ impl<'a> Codegen<'a> { sig.full_name, input_exprs.join(", "), fallible_try, - )?; + ) + .unwrap(); self.define_val(&output, ctx, /* is_ref = */ false, termdata.ret_ty); } &ExprInst::Return { @@ -893,8 +895,6 @@ impl<'a> Codegen<'a> { returns.push((index, value_expr)); } } - - Ok(()) } fn match_variant_binders( @@ -925,12 +925,12 @@ impl<'a> Codegen<'a> { /// infallible. fn generate_pattern_inst( &self, - code: &mut dyn Write, + code: &mut String, id: InstId, inst: &PatternInst, indent: &str, ctx: &mut BodyContext, - ) -> Result { + ) -> bool { match inst { &PatternInst::Arg { index, ty } => { let output = Value::Pattern { @@ -942,7 +942,7 @@ impl<'a> Codegen<'a> { &Type::Primitive(..) => false, _ => true, }; - writeln!(code, "{}let {} = arg{};", indent, outputname, index)?; + writeln!(code, "{}let {} = arg{};", indent, outputname, index).unwrap(); self.define_val( &Value::Pattern { inst: id, @@ -952,26 +952,26 @@ impl<'a> Codegen<'a> { is_ref, ty, ); - Ok(true) + true } &PatternInst::MatchEqual { ref a, ref b, .. } => { let a = self.value_by_ref(a, ctx); let b = self.value_by_ref(b, ctx); - writeln!(code, "{}if {} == {} {{", indent, a, b)?; - Ok(false) + writeln!(code, "{}if {} == {} {{", indent, a, b).unwrap(); + false } &PatternInst::MatchInt { ref input, int_val, .. } => { let input = self.value_by_val(input, ctx); - writeln!(code, "{}if {} == {} {{", indent, input, int_val)?; - Ok(false) + writeln!(code, "{}if {} == {} {{", indent, input, int_val).unwrap(); + false } &PatternInst::MatchPrim { ref input, val, .. } => { let input = self.value_by_val(input, ctx); let sym = &self.typeenv.syms[val.index()]; - writeln!(code, "{}if {} == {} {{", indent, input, sym)?; - Ok(false) + writeln!(code, "{}if {} == {} {{", indent, input, sym).unwrap(); + false } &PatternInst::MatchVariant { ref input, @@ -997,8 +997,9 @@ impl<'a> Codegen<'a> { code, "{}if let {}::{} {} = {} {{", indent, ty_name, variantname, args, input - )?; - Ok(false) + ) + .unwrap(); + false } &PatternInst::Extract { ref inputs, @@ -1035,8 +1036,9 @@ impl<'a> Codegen<'a> { output_binders.join(", "), sig.full_name, input_values.join(", "), - )?; - Ok(true) + ) + .unwrap(); + true } else { writeln!( code, @@ -1045,8 +1047,9 @@ impl<'a> Codegen<'a> { output_binders.join(", "), sig.full_name, input_values.join(", "), - )?; - Ok(false) + ) + .unwrap(); + false } } &PatternInst::Expr { @@ -1065,25 +1068,26 @@ impl<'a> Codegen<'a> { indent, self.value_name(&output), self.const_int(val, ty), - )?; + ) + .unwrap(); self.define_val(&output, ctx, /* is_ref = */ false, ty); - Ok(true) + true } &PatternInst::Expr { ref seq, output_ty, .. } => { let closure_name = format!("closure{}", id.index()); - writeln!(code, "{}let {} = || {{", indent, closure_name)?; + writeln!(code, "{}let {} = || {{", indent, closure_name).unwrap(); let subindent = format!("{} ", indent); let mut subctx = ctx.clone(); let mut returns = vec![]; for (id, inst) in seq.insts.iter().enumerate() { let id = InstId(id); - self.generate_expr_inst(code, id, inst, &subindent, &mut subctx, &mut returns)?; + self.generate_expr_inst(code, id, inst, &subindent, &mut subctx, &mut returns); } assert_eq!(returns.len(), 1); - writeln!(code, "{}return Some({});", subindent, returns[0].1)?; - writeln!(code, "{}}};", indent)?; + writeln!(code, "{}return Some({});", subindent, returns[0].1).unwrap(); + writeln!(code, "{}}};", indent).unwrap(); let output = Value::Pattern { inst: id, @@ -1095,22 +1099,23 @@ impl<'a> Codegen<'a> { indent, self.value_binder(&output, /* is_ref = */ false, output_ty), closure_name - )?; + ) + .unwrap(); self.define_val(&output, ctx, /* is_ref = */ false, output_ty); - Ok(false) + false } } } fn generate_body( &self, - code: &mut dyn Write, + code: &mut String, depth: usize, trie: &TrieNode, indent: &str, ctx: &mut BodyContext, - ) -> Result { + ) -> bool { log::trace!("generate_body: trie {:?}", trie); let mut returned = false; match trie { @@ -1122,16 +1127,17 @@ impl<'a> Codegen<'a> { "{}// Rule at {}.", indent, output.pos.pretty_print_line(&self.typeenv.filenames[..]) - )?; + ) + .unwrap(); // If this is a leaf node, generate the ExprSequence and return. let mut returns = vec![]; for (id, inst) in output.insts.iter().enumerate() { let id = InstId(id); - self.generate_expr_inst(code, id, inst, indent, ctx, &mut returns)?; + self.generate_expr_inst(code, id, inst, indent, ctx, &mut returns); } assert_eq!(returns.len(), 1); - writeln!(code, "{}return Some({});", indent, returns[0].1)?; + writeln!(code, "{}return Some({});", indent, returns[0].1).unwrap(); returned = true; } @@ -1181,7 +1187,7 @@ impl<'a> Codegen<'a> { // a `match` form if there are at least two // adjacent options. if last - i > 1 { - self.generate_body_matches(code, depth, &edges[i..last], indent, ctx)?; + self.generate_body_matches(code, depth, &edges[i..last], indent, ctx); i = last; continue; } else { @@ -1194,18 +1200,17 @@ impl<'a> Codegen<'a> { match symbol { &TrieSymbol::EndOfMatch => { - returned = - self.generate_body(code, depth + 1, node, indent, ctx)?; + returned = self.generate_body(code, depth + 1, node, indent, ctx); } &TrieSymbol::Match { ref op } => { let id = InstId(depth); let infallible = - self.generate_pattern_inst(code, id, op, indent, ctx)?; + self.generate_pattern_inst(code, id, op, indent, ctx); let i = if infallible { indent } else { &subindent[..] }; let sub_returned = - self.generate_body(code, depth + 1, node, i, ctx)?; + self.generate_body(code, depth + 1, node, i, ctx); if !infallible { - writeln!(code, "{}}}", indent)?; + writeln!(code, "{}}}", indent).unwrap(); } if infallible && sub_returned { returned = true; @@ -1218,17 +1223,17 @@ impl<'a> Codegen<'a> { } } - Ok(returned) + returned } fn generate_body_matches( &self, - code: &mut dyn Write, + code: &mut String, depth: usize, edges: &[TrieEdge], indent: &str, ctx: &mut BodyContext, - ) -> Result<(), Error> { + ) { let (input, input_ty) = match &edges[0].symbol { &TrieSymbol::Match { op: @@ -1254,7 +1259,8 @@ impl<'a> Codegen<'a> { "{}match {} {{", indent, self.value_by_ref(&input, ctx) - )?; + ) + .unwrap(); // Emit each case. for &TrieEdge { @@ -1288,18 +1294,17 @@ impl<'a> Codegen<'a> { code, "{} &{}::{} {} => {{", indent, input_ty_name, variantname, fields, - )?; + ) + .unwrap(); let subindent = format!("{} ", indent); - self.generate_body(code, depth + 1, node, &subindent, ctx)?; - writeln!(code, "{} }}", indent)?; + self.generate_body(code, depth + 1, node, &subindent, ctx); + writeln!(code, "{} }}", indent).unwrap(); } // Always add a catchall, because we don't do exhaustiveness // checking on the MatcHVariants. - writeln!(code, "{} _ => {{}}", indent)?; + writeln!(code, "{} _ => {{}}", indent).unwrap(); - writeln!(code, "{}}}", indent)?; - - Ok(()) + writeln!(code, "{}}}", indent).unwrap(); } } diff --git a/cranelift/isle/isle/src/compile.rs b/cranelift/isle/isle/src/compile.rs index 8f98b8c1c6..69d7a2aa5e 100644 --- a/cranelift/isle/isle/src/compile.rs +++ b/cranelift/isle/isle/src/compile.rs @@ -6,6 +6,6 @@ use crate::{ast, codegen, sema}; pub fn compile(defs: &ast::Defs) -> Result> { let mut typeenv = sema::TypeEnv::from_ast(defs)?; let termenv = sema::TermEnv::from_ast(&mut typeenv, defs)?; - let codegen = codegen::Codegen::compile(&typeenv, &termenv).map_err(|e| vec![e])?; - codegen.generate_rust().map_err(|e| vec![e]) + let codegen = codegen::Codegen::compile(&typeenv, &termenv); + Ok(codegen.generate_rust()) }