mirror of
https://github.com/kmc7468/cs420.git
synced 2025-12-15 23:18:48 +00:00
Format and stuff
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
use clap::Parser;
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
#[clap(name = "fuzz", version, author, about)]
|
||||
struct FuzzCli {
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
use clap::Parser;
|
||||
|
||||
use std::ffi::OsStr;
|
||||
use std::io::Write;
|
||||
use std::os::unix::io::{FromRawFd, IntoRawFd};
|
||||
use std::path::Path;
|
||||
use std::process::{Command, Stdio};
|
||||
|
||||
use lang_c::ast::TranslationUnit;
|
||||
use tempfile::tempdir;
|
||||
|
||||
use clap::Parser;
|
||||
use kecc::{
|
||||
ir, ok_or_exit, write, Asmgen, Deadcode, Gvn, IrParse, IrVisualizer, Irgen, Mem2reg, Optimize,
|
||||
Parse, SimplifyCfg, Translate, O1,
|
||||
};
|
||||
use lang_c::ast::TranslationUnit;
|
||||
use tempfile::tempdir;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
#[clap(name = "kecc", version, author, about)]
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
mod write_asm;
|
||||
|
||||
use crate::ir;
|
||||
|
||||
use core::convert::TryFrom;
|
||||
use core::fmt;
|
||||
|
||||
use crate::ir;
|
||||
|
||||
/// An assembly file.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Asm {
|
||||
|
||||
@@ -1,15 +1,24 @@
|
||||
use crate::asm;
|
||||
use crate::ir;
|
||||
use crate::Translate;
|
||||
use std::collections::{HashMap, HashSet, VecDeque};
|
||||
|
||||
#[derive(Default, Clone, Copy, Debug)]
|
||||
use lang_c::ast;
|
||||
|
||||
use crate::ir::HasDtype;
|
||||
use crate::{asm, ir, Translate};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Asmgen {}
|
||||
|
||||
impl Default for Asmgen {
|
||||
fn default() -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Translate<ir::TranslationUnit> for Asmgen {
|
||||
type Target = asm::Asm;
|
||||
type Error = ();
|
||||
|
||||
fn translate(&mut self, _source: &ir::TranslationUnit) -> Result<Self::Target, Self::Error> {
|
||||
todo!("Homework: Assembly Generation")
|
||||
fn translate(&mut self, source: &ir::TranslationUnit) -> Result<Self::Target, Self::Error> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,14 +8,14 @@ use lang_c::span::Node;
|
||||
use crate::utils::AssertSupported;
|
||||
use crate::Translate;
|
||||
|
||||
/// TODO(document)
|
||||
/// Parse Error
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
ParseError(ParseError),
|
||||
Unsupported,
|
||||
}
|
||||
|
||||
/// TODO(document)
|
||||
/// C file Parser.
|
||||
#[derive(Default, Clone, Copy, Debug)]
|
||||
pub struct Parse;
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
use std::io::{Result, Write};
|
||||
|
||||
use lang_c::ast::*;
|
||||
use lang_c::span::Node;
|
||||
|
||||
use core::ops::Deref;
|
||||
use std::io::{Result, Write};
|
||||
|
||||
use crate::write_base::*;
|
||||
|
||||
impl<T: WriteLine> WriteLine for Node<T> {
|
||||
@@ -19,8 +18,8 @@ impl<T: WriteString> WriteString for Node<T> {
|
||||
}
|
||||
|
||||
impl WriteLine for TranslationUnit {
|
||||
fn write_line(&self, _indent: usize, _write: &mut dyn Write) -> Result<()> {
|
||||
todo!("Homework: write C")
|
||||
fn write_line(&self, indent: usize, write: &mut dyn Write) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use core::convert::TryFrom;
|
||||
use core::fmt;
|
||||
use core::ops::Deref;
|
||||
use lang_c::ast;
|
||||
use lang_c::span::Node;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::hash::Hash;
|
||||
use thiserror::Error;
|
||||
|
||||
use itertools::izip;
|
||||
use lang_c::ast;
|
||||
use lang_c::span::Node;
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::ir::*;
|
||||
use crate::some_or;
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
use core::fmt;
|
||||
use core::iter;
|
||||
use core::mem;
|
||||
use ordered_float::OrderedFloat;
|
||||
use core::{fmt, iter, mem};
|
||||
use std::collections::HashMap;
|
||||
use thiserror::Error;
|
||||
|
||||
use itertools::izip;
|
||||
use ordered_float::OrderedFloat;
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::ir::*;
|
||||
use crate::*;
|
||||
@@ -410,10 +408,12 @@ impl<'i> StackFrame<'i> {
|
||||
}
|
||||
|
||||
mod calculator {
|
||||
use std::cmp::Ordering;
|
||||
|
||||
use lang_c::ast;
|
||||
|
||||
use super::Value;
|
||||
use crate::ir::*;
|
||||
use lang_c::ast;
|
||||
use std::cmp::Ordering;
|
||||
|
||||
fn calculate_integer_binary_operator_expression(
|
||||
op: &ast::BinaryOperator,
|
||||
|
||||
@@ -10,15 +10,15 @@ mod write_ir;
|
||||
use core::convert::TryFrom;
|
||||
use core::fmt;
|
||||
use core::ops::{Deref, DerefMut};
|
||||
use hexf_parse::{parse_hexf32, parse_hexf64};
|
||||
use itertools::Itertools;
|
||||
use lang_c::ast;
|
||||
use ordered_float::OrderedFloat;
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
pub use dtype::{Dtype, DtypeError, HasDtype};
|
||||
use hexf_parse::{parse_hexf32, parse_hexf64};
|
||||
pub use interp::{interp, Value};
|
||||
use itertools::Itertools;
|
||||
use lang_c::ast;
|
||||
use ordered_float::OrderedFloat;
|
||||
pub use parse::Parse;
|
||||
pub use visualize::Visualizer;
|
||||
|
||||
|
||||
@@ -5,8 +5,7 @@ use lang_c::*;
|
||||
|
||||
use crate::ir::*;
|
||||
use crate::utils::AssertSupported;
|
||||
use crate::Translate;
|
||||
use crate::*;
|
||||
use crate::{Translate, *};
|
||||
|
||||
peg::parser! {
|
||||
grammar ir_parse() for str {
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::ir::*;
|
||||
use crate::some_or;
|
||||
use crate::Translate;
|
||||
use crate::{some_or, Translate};
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct Visualizer {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use crate::ir::*;
|
||||
|
||||
use std::io::{Result, Write};
|
||||
|
||||
use crate::ir::*;
|
||||
use crate::write_base::*;
|
||||
use crate::*;
|
||||
|
||||
|
||||
@@ -34,23 +34,22 @@
|
||||
//! [irgen-stmt-1]: https://youtu.be/jFahkyxm994
|
||||
//! [irgen-stmt-2]: https://youtu.be/UkaXaNw462U
|
||||
//! [github-qna-irgen]: https://github.com/kaist-cp/cs420/labels/homework%20-%20irgen
|
||||
#![allow(dead_code)]
|
||||
use core::cmp::Ordering;
|
||||
use core::convert::TryFrom;
|
||||
use core::fmt;
|
||||
use core::mem;
|
||||
use core::{fmt, mem};
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::ops::Deref;
|
||||
|
||||
use itertools::izip;
|
||||
use lang_c::ast::*;
|
||||
use lang_c::driver::Parse;
|
||||
use lang_c::span::Node;
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::ir::{DtypeError, HasDtype, Named};
|
||||
use crate::write_base::WriteString;
|
||||
use crate::*;
|
||||
|
||||
use itertools::izip;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct IrgenError {
|
||||
pub code: String,
|
||||
@@ -69,6 +68,9 @@ impl fmt::Display for IrgenError {
|
||||
}
|
||||
}
|
||||
|
||||
/// Error format when a compiler error happens.
|
||||
///
|
||||
/// Feel free to add more kinds of errors.
|
||||
#[derive(Debug, PartialEq, Eq, Error)]
|
||||
pub enum IrgenErrorMessage {
|
||||
/// For uncommon error
|
||||
@@ -89,11 +91,17 @@ pub enum IrgenErrorMessage {
|
||||
RequireLvalue { message: String },
|
||||
}
|
||||
|
||||
/// A C file going through IR generation.
|
||||
#[derive(Default, Debug)]
|
||||
pub struct Irgen {
|
||||
/// Declarations made in the C file (e.g, global variables and functions)
|
||||
decls: BTreeMap<String, ir::Declaration>,
|
||||
/// Type definitions made in the C file (e.g, typedef my_type = int;)
|
||||
typedefs: HashMap<String, ir::Dtype>,
|
||||
/// Structs defined in the C file,
|
||||
// TODO: explain how to use this.
|
||||
structs: HashMap<String, Option<ir::Dtype>>,
|
||||
/// Temporary counter for anonymous structs. One should not need to use this any more.
|
||||
struct_tempid_counter: usize,
|
||||
}
|
||||
|
||||
@@ -112,14 +120,14 @@ impl Translate<TranslationUnit> for Irgen {
|
||||
|
||||
fn translate(&mut self, source: &TranslationUnit) -> Result<Self::Target, Self::Error> {
|
||||
for ext_decl in &source.0 {
|
||||
match ext_decl.node {
|
||||
ExternalDeclaration::Declaration(ref var) => {
|
||||
match &ext_decl.node {
|
||||
ExternalDeclaration::Declaration(var) => {
|
||||
self.add_declaration(&var.node)?;
|
||||
}
|
||||
ExternalDeclaration::StaticAssert(_) => {
|
||||
panic!("ExternalDeclaration::StaticAssert is unsupported")
|
||||
}
|
||||
ExternalDeclaration::FunctionDefinition(ref func) => {
|
||||
ExternalDeclaration::FunctionDefinition(func) => {
|
||||
self.add_function_definition(&func.node)?;
|
||||
}
|
||||
}
|
||||
@@ -513,9 +521,10 @@ impl IrgenFunc<'_> {
|
||||
}
|
||||
|
||||
/// Create a new allocation with type given by `alloc`.
|
||||
fn insert_alloc(&mut self, alloc: Named<ir::Dtype>) -> usize {
|
||||
fn insert_alloc(&mut self, alloc: Named<ir::Dtype>) -> ir::RegisterId {
|
||||
self.allocations.push(alloc);
|
||||
self.allocations.len() - 1
|
||||
let id = self.allocations.len() - 1;
|
||||
ir::RegisterId::local(id)
|
||||
}
|
||||
|
||||
/// Insert a new block `context` with exit instruction `exit`.
|
||||
@@ -551,6 +560,7 @@ impl IrgenFunc<'_> {
|
||||
/// Panics if there are no scopes to exit, i.e, the function has a unmatched `}`.
|
||||
fn exit_scope(&mut self) {
|
||||
let _unused = self.symbol_table.pop().unwrap();
|
||||
debug_assert!(!self.symbol_table.is_empty())
|
||||
}
|
||||
|
||||
/// Inserts `var` with `value` to the current symbol table.
|
||||
@@ -576,15 +586,15 @@ impl IrgenFunc<'_> {
|
||||
/// `bid_continue` and break block `bid_break`.
|
||||
fn translate_stmt(
|
||||
&mut self,
|
||||
_stmt: &Statement,
|
||||
_context: &mut Context,
|
||||
_bid_continue: Option<ir::BlockId>,
|
||||
_bid_break: Option<ir::BlockId>,
|
||||
stmt: &Statement,
|
||||
context: &mut Context,
|
||||
bid_continue: Option<ir::BlockId>,
|
||||
bid_break: Option<ir::BlockId>,
|
||||
) -> Result<(), IrgenError> {
|
||||
todo!("Homework: IR Generation")
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Translate parameter declaration of the functions to IR.
|
||||
/// Translate initial parameter declarations of the functions to IR.
|
||||
///
|
||||
/// For example, given the following C function from [`foo.c`][foo]:
|
||||
///
|
||||
@@ -610,9 +620,11 @@ impl IrgenFunc<'_> {
|
||||
/// %b0:p0:i32:x
|
||||
/// %b0:p1:i32:y
|
||||
/// %b0:p2:i32:z
|
||||
/// ...
|
||||
/// ```
|
||||
///
|
||||
/// With the following arguments :
|
||||
///
|
||||
/// ```ignore
|
||||
/// signature = FunctionSignature { ret: ir::INT, params: vec![ir::INT, ir::INT, ir::INT] }
|
||||
/// bid_init = 0
|
||||
@@ -638,6 +650,7 @@ impl IrgenFunc<'_> {
|
||||
/// %b0:i0:unit = store %b0:p0:i32 %l0:i32*
|
||||
/// %b0:i1:unit = store %b0:p1:i32 %l1:i32*
|
||||
/// %b0:i2:unit = store %b0:p2:i32 %l2:i32*
|
||||
/// ...
|
||||
/// ```
|
||||
///
|
||||
/// In particular, note that it is added to the local allocation list and store them to the
|
||||
@@ -649,12 +662,12 @@ impl IrgenFunc<'_> {
|
||||
/// [foo]: https://github.com/kaist-cp/kecc-public/blob/main/examples/c/foo.c
|
||||
fn translate_parameter_decl(
|
||||
&mut self,
|
||||
_signature: &ir::FunctionSignature,
|
||||
_bid_init: ir::BlockId,
|
||||
_name_of_params: &[String],
|
||||
_context: &mut Context,
|
||||
signature: &ir::FunctionSignature,
|
||||
bid_init: ir::BlockId,
|
||||
name_of_params: &[String],
|
||||
context: &mut Context,
|
||||
) -> Result<(), IrgenErrorMessage> {
|
||||
todo!("Homework: IR Generation")
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
84
src/lib.rs
84
src/lib.rs
@@ -5,45 +5,50 @@
|
||||
#![deny(warnings)]
|
||||
// Tries to deny all rustc allow lints.
|
||||
// <https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html>
|
||||
#![deny(absolute_paths_not_starting_with_crate)]
|
||||
#![deny(
|
||||
absolute_paths_not_starting_with_crate,
|
||||
// Old, historical lint
|
||||
// #![deny(box_pointers)]
|
||||
#![deny(elided_lifetimes_in_paths)]
|
||||
#![deny(explicit_outlives_requirements)]
|
||||
#![deny(keyword_idents)]
|
||||
#![deny(let_underscore_drop)]
|
||||
#![deny(macro_use_extern_crate)]
|
||||
#![deny(meta_variable_misuse)]
|
||||
#![deny(missing_abi)]
|
||||
#![deny(missing_copy_implementations)]
|
||||
#![deny(missing_debug_implementations)]
|
||||
// box_pointers,
|
||||
elided_lifetimes_in_paths,
|
||||
explicit_outlives_requirements,
|
||||
keyword_idents,
|
||||
let_underscore_drop,
|
||||
macro_use_extern_crate,
|
||||
meta_variable_misuse,
|
||||
missing_abi,
|
||||
// Most stuff are reasonably not copy.
|
||||
// missing_copy_implementations,
|
||||
missing_debug_implementations,
|
||||
// TODO
|
||||
// #![deny(missing_docs)]
|
||||
#![deny(non_ascii_idents)]
|
||||
#![deny(noop_method_call)]
|
||||
#![deny(rust_2021_incompatible_closure_captures)]
|
||||
#![deny(rust_2021_incompatible_or_patterns)]
|
||||
#![deny(rust_2021_prefixes_incompatible_syntax)]
|
||||
#![deny(rust_2021_prelude_collisions)]
|
||||
// missing_docs
|
||||
non_ascii_idents,
|
||||
noop_method_call,
|
||||
rust_2021_incompatible_closure_captures,
|
||||
rust_2021_incompatible_or_patterns,
|
||||
rust_2021_prefixes_incompatible_syntax,
|
||||
rust_2021_prelude_collisions,
|
||||
// Necessary for skeleton code.
|
||||
// #![deny(single_use_lifetimes)]
|
||||
#![deny(trivial_casts)]
|
||||
#![deny(trivial_numeric_casts)]
|
||||
// single_use_lifetimes,
|
||||
trivial_casts,
|
||||
trivial_numeric_casts,
|
||||
// Necessary for skeleton code.
|
||||
// #![deny(unreachable_pub)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
#![deny(unstable_features)]
|
||||
// unreachable_pub,
|
||||
unsafe_code,
|
||||
unsafe_op_in_unsafe_fn,
|
||||
unstable_features,
|
||||
// Necessary for `build-bin` trick.
|
||||
// #![deny(unused_crate_dependencies)]
|
||||
#![deny(unused_extern_crates)]
|
||||
#![deny(unused_import_braces)]
|
||||
#![deny(unused_lifetimes)]
|
||||
#![deny(unused_macro_rules)]
|
||||
#![deny(unused_qualifications)]
|
||||
#![deny(unused_results)]
|
||||
// unused_crate_dependencies,
|
||||
unused_extern_crates,
|
||||
unused_import_braces,
|
||||
unused_lifetimes,
|
||||
unused_macro_rules,
|
||||
unused_qualifications,
|
||||
unused_results,
|
||||
// Allowed for more flexible variants.
|
||||
// #![deny(variant_size_differences)]
|
||||
// variant_size_differences,
|
||||
)]
|
||||
// For skeleton code.
|
||||
#![allow(unused)]
|
||||
|
||||
mod tests;
|
||||
mod utils;
|
||||
@@ -57,17 +62,14 @@ mod asmgen;
|
||||
mod irgen;
|
||||
mod opt;
|
||||
|
||||
pub use tests::*;
|
||||
pub use utils::*;
|
||||
pub use write_base::write;
|
||||
|
||||
pub use c::Parse;
|
||||
pub use ir::Parse as IrParse;
|
||||
pub use ir::Visualizer as IrVisualizer;
|
||||
|
||||
pub use asmgen::Asmgen;
|
||||
pub use c::Parse;
|
||||
pub use ir::{Parse as IrParse, Visualizer as IrVisualizer};
|
||||
pub use irgen::Irgen;
|
||||
pub use opt::{
|
||||
Deadcode, FunctionPass, Gvn, Mem2reg, Optimize, Repeat, SimplifyCfg, SimplifyCfgConstProp,
|
||||
SimplifyCfgEmpty, SimplifyCfgMerge, SimplifyCfgReach, O0, O1,
|
||||
};
|
||||
pub use tests::*;
|
||||
pub use utils::*;
|
||||
pub use write_base::write;
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
use core::ops::Deref;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use crate::ir::*;
|
||||
use crate::opt::FunctionPass;
|
||||
use crate::*;
|
||||
use crate::opt::opt_utils::*;
|
||||
use crate::opt::*;
|
||||
|
||||
pub type Deadcode = FunctionPass<Repeat<DeadcodeInner>>;
|
||||
|
||||
@@ -8,7 +11,7 @@ pub type Deadcode = FunctionPass<Repeat<DeadcodeInner>>;
|
||||
pub struct DeadcodeInner {}
|
||||
|
||||
impl Optimize<FunctionDefinition> for DeadcodeInner {
|
||||
fn optimize(&mut self, _code: &mut FunctionDefinition) -> bool {
|
||||
todo!("Homework: Deadcode Elimination")
|
||||
fn optimize(&mut self, code: &mut FunctionDefinition) -> bool {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
use crate::opt::FunctionPass;
|
||||
use crate::*;
|
||||
use core::ops::Deref;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use itertools::izip;
|
||||
use lang_c::ast;
|
||||
|
||||
use crate::ir::*;
|
||||
use crate::opt::opt_utils::*;
|
||||
use crate::opt::*;
|
||||
|
||||
pub type Gvn = FunctionPass<GvnInner>;
|
||||
|
||||
#[derive(Default, Clone, Copy, Debug)]
|
||||
pub struct GvnInner {}
|
||||
|
||||
impl Optimize<ir::FunctionDefinition> for GvnInner {
|
||||
fn optimize(&mut self, _code: &mut ir::FunctionDefinition) -> bool {
|
||||
todo!("Homework: Global Variable Numbering")
|
||||
impl Optimize<FunctionDefinition> for GvnInner {
|
||||
fn optimize(&mut self, code: &mut FunctionDefinition) -> bool {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
use core::ops::{Deref, DerefMut};
|
||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||
|
||||
use crate::ir::*;
|
||||
use crate::opt::FunctionPass;
|
||||
use crate::*;
|
||||
use crate::opt::opt_utils::*;
|
||||
use crate::opt::*;
|
||||
|
||||
pub type Mem2reg = FunctionPass<Mem2regInner>;
|
||||
|
||||
@@ -8,7 +11,7 @@ pub type Mem2reg = FunctionPass<Mem2regInner>;
|
||||
pub struct Mem2regInner {}
|
||||
|
||||
impl Optimize<FunctionDefinition> for Mem2regInner {
|
||||
fn optimize(&mut self, _code: &mut FunctionDefinition) -> bool {
|
||||
todo!("Homework: Register Promotion")
|
||||
fn optimize(&mut self, code: &mut FunctionDefinition) -> bool {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//! Utilities for implementing optimizations.
|
||||
//!
|
||||
//! You can add here utilities commonly used in the implementation of multiple optimizations.
|
||||
//! You can freely add utilities commonly used in the implementation of multiple optimizations here.
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::ops::Deref;
|
||||
|
||||
use itertools::izip;
|
||||
|
||||
use crate::ir::*;
|
||||
use crate::opt::FunctionPass;
|
||||
use crate::*;
|
||||
use crate::opt::opt_utils::*;
|
||||
use crate::opt::*;
|
||||
|
||||
pub type SimplifyCfg = FunctionPass<
|
||||
Repeat<(
|
||||
@@ -26,25 +31,25 @@ pub struct SimplifyCfgMerge {}
|
||||
pub struct SimplifyCfgEmpty {}
|
||||
|
||||
impl Optimize<FunctionDefinition> for SimplifyCfgConstProp {
|
||||
fn optimize(&mut self, _code: &mut FunctionDefinition) -> bool {
|
||||
todo!("Homework: Simplify CFG")
|
||||
fn optimize(&mut self, code: &mut FunctionDefinition) -> bool {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Optimize<FunctionDefinition> for SimplifyCfgReach {
|
||||
fn optimize(&mut self, _code: &mut FunctionDefinition) -> bool {
|
||||
todo!("Homework: Simplify CFG")
|
||||
fn optimize(&mut self, code: &mut FunctionDefinition) -> bool {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Optimize<FunctionDefinition> for SimplifyCfgMerge {
|
||||
fn optimize(&mut self, _code: &mut FunctionDefinition) -> bool {
|
||||
todo!("Homework: Simplify CFG")
|
||||
fn optimize(&mut self, code: &mut FunctionDefinition) -> bool {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Optimize<FunctionDefinition> for SimplifyCfgEmpty {
|
||||
fn optimize(&mut self, _code: &mut FunctionDefinition) -> bool {
|
||||
todo!("Homework: Simplify CFG")
|
||||
fn optimize(&mut self, code: &mut FunctionDefinition) -> bool {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use lang_c::*;
|
||||
use rand::Rng;
|
||||
use std::fs::{self, File};
|
||||
use std::io::{stderr, Read, Write};
|
||||
use std::path::Path;
|
||||
use std::process::{Command, Stdio};
|
||||
|
||||
use lang_c::*;
|
||||
use rand::Rng;
|
||||
use tempfile::tempdir;
|
||||
use wait_timeout::ChildExt;
|
||||
|
||||
|
||||
40
src/utils.rs
40
src/utils.rs
@@ -1,11 +1,7 @@
|
||||
use itertools::izip;
|
||||
|
||||
use core::ops::Deref;
|
||||
|
||||
#[macro_export]
|
||||
/// Ok or executing the given expression.
|
||||
macro_rules! ok_or {
|
||||
($e:expr, $err:expr) => {{
|
||||
($e:expr_2021, $err:expr_2021) => {{
|
||||
match $e {
|
||||
Ok(r) => r,
|
||||
Err(_) => $err,
|
||||
@@ -16,7 +12,7 @@ macro_rules! ok_or {
|
||||
#[macro_export]
|
||||
/// Some or executing the given expression.
|
||||
macro_rules! some_or {
|
||||
($e:expr, $err:expr) => {{
|
||||
($e:expr_2021, $err:expr_2021) => {{
|
||||
match $e {
|
||||
Some(r) => r,
|
||||
None => $err,
|
||||
@@ -27,7 +23,7 @@ macro_rules! some_or {
|
||||
#[macro_export]
|
||||
/// Ok or exiting the process.
|
||||
macro_rules! ok_or_exit {
|
||||
($e:expr, $code:expr) => {{
|
||||
($e:expr_2021, $code:expr_2021) => {{
|
||||
match $e {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
@@ -41,7 +37,7 @@ macro_rules! ok_or_exit {
|
||||
#[macro_export]
|
||||
/// Ok or exiting the process.
|
||||
macro_rules! some_or_exit {
|
||||
($e:expr, $code:expr) => {{
|
||||
($e:expr_2021, $code:expr_2021) => {{
|
||||
match $e {
|
||||
Some(r) => r,
|
||||
None => ::std::process::exit($code),
|
||||
@@ -49,33 +45,41 @@ macro_rules! some_or_exit {
|
||||
}};
|
||||
}
|
||||
|
||||
/// TODO(document)
|
||||
/// Translates `S` to [`Translate::Target`].
|
||||
// TODO: Should this be in utils?
|
||||
pub trait Translate<S> {
|
||||
/// TODO(document)
|
||||
/// The type to translate to.
|
||||
type Target;
|
||||
|
||||
/// TODO(document)
|
||||
/// The error type.
|
||||
type Error;
|
||||
|
||||
/// TODO(document)
|
||||
/// Translate `source` to `Self::Target`.
|
||||
fn translate(&mut self, source: &S) -> Result<Self::Target, Self::Error>;
|
||||
}
|
||||
|
||||
/// TODO(document)
|
||||
/// Trait to check if a type can be translated.
|
||||
pub trait AssertSupported {
|
||||
/// TODO(document)
|
||||
/// Assert that the type can be translated.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the type can't be translated.
|
||||
// TODO: should return a boolean.
|
||||
fn assert_supported(&self);
|
||||
}
|
||||
|
||||
/// TODO(document)
|
||||
/// Essentially the same as [`PartialEq`].
|
||||
///
|
||||
/// Exists to check equaility on some foreign types.
|
||||
pub trait IsEquiv {
|
||||
/// TODO(document)
|
||||
/// See [`PartialEq::eq`].
|
||||
fn is_equiv(&self, other: &Self) -> bool;
|
||||
}
|
||||
|
||||
impl<T: IsEquiv> IsEquiv for Box<T> {
|
||||
fn is_equiv(&self, other: &Self) -> bool {
|
||||
self.deref().is_equiv(other.deref())
|
||||
(**self).is_equiv(&**other)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +101,6 @@ impl<T: IsEquiv> IsEquiv for Option<T> {
|
||||
|
||||
impl<T: IsEquiv> IsEquiv for Vec<T> {
|
||||
fn is_equiv(&self, other: &Self) -> bool {
|
||||
self.len() == other.len() && izip!(self, other).all(|(lhs, rhs)| lhs.is_equiv(rhs))
|
||||
self.len() == other.len() && self.iter().zip(other).all(|(lhs, rhs)| lhs.is_equiv(rhs))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use std::io::{Result, Write};
|
||||
|
||||
/// Write `indent` number of double spaces to `write`.
|
||||
#[inline]
|
||||
pub fn write_indent(indent: usize, write: &mut dyn Write) -> Result<()> {
|
||||
write!(write, "{}", " ".repeat(indent))
|
||||
}
|
||||
@@ -9,24 +8,21 @@ pub fn write_indent(indent: usize, write: &mut dyn Write) -> Result<()> {
|
||||
/// A trait for writing a type to a `Write` stream with a new line.
|
||||
pub trait WriteLine {
|
||||
/// Write `self` to `write`, starting at `indent` number of double spaces, with a newline at the
|
||||
/// ned.
|
||||
/// end.
|
||||
fn write_line(&self, indent: usize, write: &mut dyn Write) -> Result<()>;
|
||||
}
|
||||
|
||||
/// Format types to a String.
|
||||
/// Essentially the same as [`ToString`].
|
||||
///
|
||||
/// Most cases, `fmt::Display` is used to format a type to a string. However, in some cases, we
|
||||
/// can't implement `fmt::Display` for a type as it is defined in another crate. In such cases, we
|
||||
/// can implement this trait to format the type to a string.
|
||||
/// Exists to make some foreign types into a string.
|
||||
pub trait WriteString {
|
||||
/// Change a type into a String.
|
||||
/// See [`ToString::to_string`].
|
||||
fn write_string(&self) -> String;
|
||||
}
|
||||
|
||||
impl<T: WriteString> WriteString for Box<T> {
|
||||
fn write_string(&self) -> String {
|
||||
use core::ops::Deref;
|
||||
self.deref().write_string()
|
||||
(**self).write_string()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +32,7 @@ impl<T: WriteString> WriteString for &T {
|
||||
}
|
||||
}
|
||||
|
||||
// Might be useful for debugging.
|
||||
impl<T: WriteString> WriteString for Option<T> {
|
||||
fn write_string(&self) -> String {
|
||||
if let Some(this) = self {
|
||||
|
||||
Reference in New Issue
Block a user