Update skeleton

This commit is contained in:
Jeehoon Kang
2020-05-02 07:52:40 +00:00
parent 3bef06455e
commit f4dc5e426c
11 changed files with 142 additions and 15 deletions

View File

@@ -1,5 +1,5 @@
int main() { int main() {
char a = -1; char a = 127;
char b = a << 1; char b = a << 1;
unsigned char c = (unsigned char)b >> 1; unsigned char c = (unsigned char)b >> 1;

44
examples/gvn/gvn.input.ir Normal file
View File

@@ -0,0 +1,44 @@
fun unit @sink {
init:
bid: b0
allocations:
block b0:
%b0:p0:i32
ret unit:unit
}
fun i32 @gvn {
init:
bid: b0
allocations:
block b0:
%b0:p0:i32:a
%b0:i0:i32:b = add %b0:p0:i32 1:i32
br undef:i1 b1() b2()
block b1:
%b1:i0:i32:b = add %b0:p0:i32 1:i32
%b1:i1:i32:c = add %b1:i0:i32 2:i32
%b1:i2:unit = call @sink(%b1:i0:i32)
j b3()
block b2:
%b2:i0:i32:c = add %b0:i0:i32 2:i32
%b2:i1:unit = call @sink(%b2:i0:i32)
j b3()
block b3:
%b3:i0:i32:b = add %b0:p0:i32 1:i32
%b3:i1:i32:c = add %b3:i0:i32 2:i32
%b3:i2:unit = call @sink(%b3:i0:i32)
%b3:i3:unit = call @sink(%b3:i1:i32)
ret 0:i32
}

View File

@@ -0,0 +1,46 @@
fun unit @sink {
init:
bid: b0
allocations:
block b0:
%b0:p0:i32
ret unit:unit
}
fun i32 @gvn {
init:
bid: b0
allocations:
block b0:
%b0:p0:i32:a
%b0:i0:i32:b = add %b0:p0:i32 1:i32
br undef:i1 b1() b2()
block b1:
%b1:i0:i32:b = add %b0:p0:i32 1:i32
%b1:i1:i32:c = add %b0:i0:i32 2:i32
%b1:i2:unit = call @sink(%b0:i0:i32)
j b3(%b1:i1:i32)
block b2:
%b2:i0:i32:c = add %b0:i0:i32 2:i32
%b2:i1:unit = call @sink(%b2:i0:i32)
j b3(%b2:i0:i32)
block b3:
%b3:p0:i32
%b3:i0:i32:b = add %b0:p0:i32 1:i32
%b3:i1:i32:c = add %b0:i0:i32 2:i32
%b3:i2:unit = call @sink(%b0:i0:i32)
%b3:i3:unit = call @sink(%b3:p0:i32)
ret 0:i32
}

View File

@@ -45,17 +45,15 @@ block b0:
%b0:i3:unit = nop %b0:i3:unit = nop
%b0:i4:i32 = load %l0:*i32 %b0:i4:i32 = load %l0:*i32
j b1(37:i32) j b1()
block b1: block b1:
%b1:p0:i32:x
%b1:i0:i32 = load %l0:*i32 %b1:i0:i32 = load %l0:*i32
%b1:i1:unit = call @sink(undef:i32) %b1:i1:unit = call @sink(undef:i32)
%b1:i2:unit = call @sink(42:i32) %b1:i2:unit = call @sink(42:i32)
%b1:i3:unit = call @sink(37:i32) %b1:i3:unit = call @sink(37:i32)
%b1:i4:unit = call @sink(%b1:p0:i32) %b1:i4:unit = call @sink(37:i32)
ret 0:i32 ret 0:i32
} }

View File

@@ -9,7 +9,7 @@ use core::ops::{Deref, DerefMut};
use hexf::{parse_hexf32, parse_hexf64}; use hexf::{parse_hexf32, parse_hexf64};
use lang_c::ast; use lang_c::ast;
use ordered_float::OrderedFloat; use ordered_float::OrderedFloat;
use std::collections::HashMap; use std::collections::{BTreeMap, HashMap};
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
pub use dtype::{Dtype, DtypeError, HasDtype}; pub use dtype::{Dtype, DtypeError, HasDtype};
@@ -18,7 +18,7 @@ pub use parse::Parse;
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct TranslationUnit { pub struct TranslationUnit {
pub decls: HashMap<String, Declaration>, pub decls: BTreeMap<String, Declaration>,
pub structs: HashMap<String, Option<Dtype>>, pub structs: HashMap<String, Option<Dtype>>,
} }
@@ -161,7 +161,7 @@ pub struct FunctionDefinition {
pub allocations: Vec<Named<Dtype>>, pub allocations: Vec<Named<Dtype>>,
/// Basic blocks. /// Basic blocks.
pub blocks: HashMap<BlockId, Block>, pub blocks: BTreeMap<BlockId, Block>,
/// The initial block id. /// The initial block id.
pub bid_init: BlockId, pub bid_init: BlockId,

View File

@@ -16,7 +16,7 @@ peg::parser! {
pub rule translation_unit() -> TranslationUnit pub rule translation_unit() -> TranslationUnit
= _ ds:(named_decl() ** __) _ { = _ ds:(named_decl() ** __) _ {
let mut decls = HashMap::new(); let mut decls = BTreeMap::new();
for decl in ds { for decl in ds {
let result = decls.insert(decl.name.unwrap(), decl.inner); let result = decls.insert(decl.name.unwrap(), decl.inner);
assert!(result.is_none()); assert!(result.is_none());

View File

@@ -1,7 +1,7 @@
use crate::opt::FunctionPass; use crate::opt::FunctionPass;
use crate::*; use crate::*;
pub type Gvn = FunctionPass<Repeat<GvnInner>>; pub type Gvn = FunctionPass<GvnInner>;
#[derive(Default)] #[derive(Default)]
pub struct GvnInner {} pub struct GvnInner {}

View File

@@ -0,0 +1,3 @@
//! Utilities for implementing optimizations.
//!
//! You can add here utilities commonly used in the implementation of multiple optimizations.

View File

@@ -1,6 +1,6 @@
use lang_c::ast::*; use lang_c::ast::*;
use std::fs::{self, File}; use std::fs::{self, File};
use std::io::{stderr, Write}; use std::io::{stderr, Read, Write};
use std::path::Path; use std::path::Path;
use std::process::{Command, Stdio}; use std::process::{Command, Stdio};
use tempfile::tempdir; use tempfile::tempdir;
@@ -41,7 +41,14 @@ pub fn test_irgen(unit: &TranslationUnit, path: &Path) {
// Compile c file: If fails, test is vacuously success // Compile c file: If fails, test is vacuously success
if !Command::new("gcc") if !Command::new("gcc")
.args(&["-O1", &file_path, "-o", &bin_path]) .args(&[
"-fsanitize=undefined",
"-fno-sanitize-recover=all",
"-O1",
&file_path,
"-o",
&bin_path,
])
.stderr(Stdio::null()) .stderr(Stdio::null())
.status() .status()
.unwrap() .unwrap()
@@ -52,6 +59,7 @@ pub fn test_irgen(unit: &TranslationUnit, path: &Path) {
// Execute compiled executable // Execute compiled executable
let mut child = Command::new(fs::canonicalize(bin_path.clone()).unwrap()) let mut child = Command::new(fs::canonicalize(bin_path.clone()).unwrap())
.stderr(Stdio::piped())
.spawn() .spawn()
.expect("failed to execute the compiled executable"); .expect("failed to execute the compiled executable");
@@ -71,6 +79,18 @@ pub fn test_irgen(unit: &TranslationUnit, path: &Path) {
::std::process::exit(SKIP_TEST); ::std::process::exit(SKIP_TEST);
} }
); );
if child
.stderr
.expect("`stderr` of `child` must be `Some`")
.bytes()
.next()
.is_some()
{
println!("error occurs");
::std::process::exit(SKIP_TEST);
}
let status = some_or_exit!(status.code(), SKIP_TEST); let status = some_or_exit!(status.code(), SKIP_TEST);
let ir = match Irgen::default().translate(unit) { let ir = match Irgen::default().translate(unit) {

View File

@@ -30,6 +30,7 @@ if
grep 'too many arguments in call' out.txt ||\ grep 'too many arguments in call' out.txt ||\
grep 'declaration does not declare anything' out.txt ||\ grep 'declaration does not declare anything' out.txt ||\
grep 'not equal to a null pointer is always true' out.txt ||\ grep 'not equal to a null pointer is always true' out.txt ||\
grep 'empty struct is a GNU extension' out.txt ||\
! gcc -Wall -Wextra -O2 test_reduced.c > outa.txt 2>&1 ||\ ! gcc -Wall -Wextra -O2 test_reduced.c > outa.txt 2>&1 ||\
grep 'uninitialized' outa.txt ||\ grep 'uninitialized' outa.txt ||\
grep 'without a cast' outa.txt ||\ grep 'without a cast' outa.txt ||\
@@ -49,10 +50,16 @@ if
grep 'excess elements in struct initializer' outa.txt ||\ grep 'excess elements in struct initializer' outa.txt ||\
grep 'comparison between pointer and integer' outa.txt ||\ grep 'comparison between pointer and integer' outa.txt ||\
! gcc -O1 test_reduced.c > cc_out1.txt 2>&1 ||\ ! gcc -O1 test_reduced.c > cc_out1.txt 2>&1 ||\
! gcc -O2 test_reduced.c > cc_out2.txt 2>&1) ! gcc -O2 test_reduced.c > cc_out2.txt 2>&1 ||\
! cargo run --manifest-path $PROJECT_DIR/Cargo.toml --release -- --parse test_reduced.c >/dev/null 2>&1)
then then
exit 1 exit 1
fi fi
cargo run --manifest-path $PROJECT_DIR/Cargo.toml --release -- --parse test_reduced.c >/dev/null 2>&1 &&\ cargo run --manifest-path $PROJECT_DIR/Cargo.toml --release --bin fuzz -- $FUZZ_ARG test_reduced.c
! cargo run --manifest-path $PROJECT_DIR/Cargo.toml --release --bin fuzz -- $FUZZ_ARG test_reduced.c if [ "$?" = 101 ]
then
exit 0
else
exit 1
fi

View File

@@ -83,3 +83,12 @@ fn test_examples_mem2reg() {
&mut Mem2reg::default(), &mut Mem2reg::default(),
); );
} }
#[test]
fn test_examples_gvn() {
test_opt(
&Path::new("examples/gvn/gvn.input.ir"),
&Path::new("examples/gvn/gvn.output.ir"),
&mut Gvn::default(),
);
}