Skip to content

Commit

Permalink
Merge pull request #37 from adam-mcdaniel/optimize-index
Browse files Browse the repository at this point in the history
Optimized generated assembly for index operations
  • Loading branch information
adam-mcdaniel authored Jun 14, 2023
2 parents 65f2e71 + c4b9d29 commit bd9a17c
Show file tree
Hide file tree
Showing 8 changed files with 41 additions and 51 deletions.
7 changes: 0 additions & 7 deletions src/frontend/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ struct FrontendParser;

#[derive(Clone, Debug)]
pub enum Statement {
Match(Expr, Vec<(Pattern, Self)>),
Let(Vec<(String, Option<Type>, Expr)>),
Assign(Expr, Option<Box<dyn AssignOp + 'static>>, Expr),
If(Expr, Box<Self>, Option<Box<Self>>),
Expand All @@ -36,12 +35,6 @@ impl Statement {
// }, rest_expr])

let stmt = match (self, rest.clone()) {
(Self::Match(e, arms), _) => Expr::Match(
Box::new(e),
arms.into_iter()
.map(|(a, b)| (a, b.to_expr(None)))
.collect(),
),
(Self::Assign(lhs, op, rhs), _) => {
match op {
Some(op) => lhs.refer().assign(op, rhs),
Expand Down
20 changes: 15 additions & 5 deletions src/lir/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ impl Compile for Expr {
Self::EnumUnion(mut t, variant, val) => {
// Get the size of the tagged union.
let result_size = t.get_size(env)?;
t = t.simplify_until_matches(env, Type::EnumUnion(BTreeMap::new()), |t, env| {
t = t.simplify_until_matches(env, Type::EnumUnion(BTreeMap::new()), |t, _env| {
Ok(!matches!(
t,
Type::Let(_, _, _) | Type::Symbol(_) | Type::Apply(_, _) | Type::Poly(_, _)
Expand Down Expand Up @@ -522,10 +522,20 @@ impl Compile for Expr {
.as_type(Type::Pointer(elem.clone()))
// Index the new pointer
.idx(*idx.clone());
// Push to the stack
// if optimized_idx.type_check(env).is_ok() {
// return optimized_idx.compile_expr(env, output);
// }
// The optimized index *may not be possible* if the array is
// not able to be referenced (like an array literal). Type checking
// a reference operation will confirm that the array is able to be
// referenced. If the array is not a:
// 1. Dereference
// 2. Index access
// 3. Member access
// 4. Variable
// If the array is a literal, then we will have to push the array
// on the stack and essentially do the same address calculations,
// but the difference is that the operation is not in-place.
if optimized_idx.type_check(env).is_ok() {
return optimized_idx.compile_expr(env, output);
}

// Get the size of the element we will return.
let elem_size = elem.get_size(env)?;
Expand Down
2 changes: 1 addition & 1 deletion src/lir/expr/const_expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::lir::{
};

use core::fmt;
use std::collections::{BTreeMap, HashMap};
use std::collections::BTreeMap;

/// A compiletime expression.
#[derive(Clone, Debug, PartialEq)]
Expand Down
2 changes: 1 addition & 1 deletion src/lir/expr/procedure/poly.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ impl PolyProcedure {
})
.collect::<Result<Vec<_>, Error>>()?;

let bind_type_args = |mut ty: Type| -> Result<Type, Error> {
let bind_type_args = |ty: Type| -> Result<Type, Error> {
// for (name, arg) in self.ty_params.iter().zip(ty_args.iter()) {
// // ty = Type::let_bind(name, if arg == &Type::Symbol(name.clone()) {
// // Type::Unit(name.clone(), Box::new(Type::Any))
Expand Down
11 changes: 8 additions & 3 deletions src/lir/types/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -493,8 +493,13 @@ impl TypeCheck for Expr {
Self::Refer(e) => match *e.clone() {
Expr::ConstExpr(ConstExpr::Symbol(_))
| Expr::Deref(_)
| Expr::Member(_, _)
| Expr::Index(_, _) => e.type_check(env),
Expr::Member(inner, _) => {
// Confirm that the inner expression can be referenced.
inner.refer().type_check(env)?;
// If so, then make sure the expression being accessed is also sound.
e.type_check(env)
},
other => Err(Error::InvalidRefer(other.clone())),
},
// Typecheck a dereference of a pointer.
Expand Down Expand Up @@ -912,8 +917,8 @@ impl TypeCheck for ConstExpr {
cast_ty.clone(),
));
}
// If it is, return success.
Ok(())
// If it is, return the result of the inner expression's typechecking result.
expr.type_check(env)
}

// Get the size of an expression in cells.
Expand Down
36 changes: 9 additions & 27 deletions src/lir/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,10 @@ impl Type {
}
}

// pub fn contains(&self,)

/// Simplify an expression until it matches a given function.
/// Simplify an expression until it matches a given function which "approves" of a type.
/// This will perform template applications to simplify the type if possible as well.
///
/// This is the **prefered** way to simplify a type into a concrete type.
pub fn simplify_until_matches(
self,
env: &Env,
Expand All @@ -156,11 +157,7 @@ impl Type {
if f(&simplified, env)? || simplified.is_atomic() {
return Ok(simplified);
}
simplified = simplified.simplify(env)?.perform_template_applications(
env,
&mut HashMap::new(),
0,
)?
simplified = simplified.simplify(env)?.perform_template_applications(env, &mut HashMap::new())?
}
Err(Error::CouldntSimplify(simplified, expected))
}
Expand Down Expand Up @@ -476,7 +473,6 @@ impl Type {
&self,
env: &Env,
previous_applications: &mut HashMap<(Type, Vec<Type>), Type>,
i: usize,
) -> Result<Self, Error> {
// If the type is an Apply on a Poly, then we can perform the application.
// First, perform the applications on the type arguments.
Expand All @@ -497,25 +493,19 @@ impl Type {

match poly {
Self::Poly(params, template) => {
let save = template.clone();
let mut template = *template;
for (param, ty_arg) in params.iter().zip(ty_args.iter()) {
template = template.substitute(param, ty_arg);
}
// template = template.simplify(env)?;
// previous_applications.insert((Self::Poly(params, save), ty_args), template.clone());
Ok(template)
}
Self::Symbol(s) => {
match env.get_type(s.as_str()).cloned() {
Some(Self::Poly(params, template)) => {
let save = template.clone();
let mut template = *template;
for (param, ty_arg) in params.iter().zip(ty_args.iter()) {
template = template.substitute(param, ty_arg);
}
// template = template.simplify(env)?;
// previous_applications.insert((Self::Poly(params, save), ty_args), template.clone());
Ok(template)
}
Some(other) => Ok(Self::Apply(Box::new(other), ty_args)),
Expand Down Expand Up @@ -771,14 +761,12 @@ impl Type {
}

(Self::Apply(poly, ty_args), b) | (b, Self::Apply(poly, ty_args)) => {
let a = Self::Apply(poly.clone(), ty_args.clone());
// If the type is a polymorphic type, then we need to simplify it first.
let f = poly.clone().simplify_until_matches(
env,
Type::Poly(vec![], Box::new(Type::Any)),
|t, env| Ok(matches!(t, Type::Poly(_, _))),
|t, _env| Ok(matches!(t, Type::Poly(_, _))),
)?;
// let a = a.simplify_until_matches(env, Type::Any, |t, env| Ok(t.is_simple()))?;

match f {
Self::Poly(ty_params, mut template) => {
Expand All @@ -789,12 +777,6 @@ impl Type {
}
template.equals_checked(b, compared_symbols, env, i)?
}
// // Self::Symbol(_) => {
// // // If the type is not a polymorphic type, then we can compare it to the
// // // other type.
// // // return a.equals_checked(b, compared_symbols, env, i);
// // false
// // }
_ => {
// If the type is not a polymorphic type, then we can compare it to the
// other type.
Expand Down Expand Up @@ -873,7 +855,7 @@ impl Type {
Type::Apply(_, _) | Type::Poly(_, _) => {
let t = self
.clone()
.simplify_until_matches(env, Type::Any, |t, env| {
.simplify_until_matches(env, Type::Any, |t, _env| {
Ok(!matches!(
t,
Type::Let(_, _, _)
Expand Down Expand Up @@ -958,7 +940,7 @@ impl Type {
Type::Apply(_, _) | Type::Poly(_, _) => {
let t = self
.clone()
.simplify_until_matches(env, Type::Any, |t, env| {
.simplify_until_matches(env, Type::Any, |t, _env| {
Ok(!matches!(
t,
Type::Let(_, _, _)
Expand Down Expand Up @@ -1179,7 +1161,7 @@ impl fmt::Display for Type {
}

Self::Symbol(name) => write!(f, "{name}"),
Self::Unit(unit_name, ty) => write!(f, "unit {unit_name}"),
Self::Unit(unit_name, _ty) => write!(f, "unit {unit_name}"),
Self::Let(name, ty, ret) => write!(f, "let {name} = {ty} in {ret}"),
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/lir/types/size.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,15 +150,15 @@ impl GetSize for Type {
}

// Get the size of an `Apply` type.
Self::Apply(poly, ty_args) => {
Self::Apply(poly, _ty_args) => {
if let Ok(size) = poly.get_size_checked(env, i) {
return Ok(size);
}

let result = self.clone().simplify_until_matches(
env,
Type::Poly(vec![], Box::new(Type::Any)),
|t, env| Ok(t.is_simple()),
|t, _env| Ok(t.is_simple()),
)?;

result.get_size_checked(env, i)?
Expand Down
10 changes: 5 additions & 5 deletions src/targets/x86.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ impl Architecture for X86 {
})
}

fn end(&mut self, matching: &CoreOp, fun: Option<usize>) -> String {
fn end(&mut self, matching: &CoreOp, _fun: Option<usize>) -> String {
match matching {
CoreOp::Function => {
let label = self.branch_match.pop().unwrap();
Expand All @@ -213,7 +213,7 @@ impl Architecture for X86 {
}
}

fn declare_proc(&mut self, label_id: usize) -> String {
fn declare_proc(&mut self, _label_id: usize) -> String {
let result = format!("movq $fun{fun_count}, funs+{}(%rip)\n{indent}jmp fun_end{fun_count}\nfun{fun_count}:\n{indent}pushq %rbp\n{indent}movq %rsp, %rbp\n", self.fun_count * 8, fun_count = self.fun_count, indent = self.indentation().unwrap());
self.branch_match
.push(format!("fun_end{fun_count}", fun_count = self.fun_count));
Expand Down Expand Up @@ -278,15 +278,15 @@ addq $8, %rsp # Deallocate the space on the stack",
// Ok("*ptr = reg;".to_string())
todo!()
}
fn prelude(&self, is_core: bool) -> Option<String> {
let mut result = ".text
fn prelude(&self, _is_core: bool) -> Option<String> {
let result = ".text
.globl main
main:
";
Some(result.to_string())
}

fn post_funs(&self, funs: Vec<i32>) -> Option<String> {
fn post_funs(&self, _funs: Vec<i32>) -> Option<String> {
None
}

Expand Down

0 comments on commit bd9a17c

Please sign in to comment.