Update IR

This commit is contained in:
Jeehoon Kang
2020-04-09 13:04:23 +09:00
parent cef3fb7650
commit 6edb4665c0
10 changed files with 196 additions and 39 deletions

76
Cargo.lock generated
View File

@@ -116,6 +116,31 @@ dependencies = [
"libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "hexf"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"hexf-impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hexf-parse 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro-hack 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "hexf-impl"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"hexf-parse 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro-hack 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "hexf-parse"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "itertools"
version = "0.9.0"
@@ -130,6 +155,7 @@ version = "0.1.0"
dependencies = [
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
"failure 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"hexf 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lang-c 0.8.0 (git+https://github.com/kaist-cp/lang-c)",
"ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -167,6 +193,19 @@ name = "ppv-lite86"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "proc-macro-hack"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro-hack-impl 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "proc-macro-hack-impl"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "proc-macro2"
version = "1.0.10"
@@ -175,6 +214,11 @@ dependencies = [
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quote"
version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "quote"
version = "1.0.3"
@@ -243,6 +287,16 @@ name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "syn"
version = "0.11.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "syn"
version = "1.0.17"
@@ -253,6 +307,14 @@ dependencies = [
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "synom"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "synstructure"
version = "0.12.3"
@@ -290,6 +352,11 @@ name = "unicode-width"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicode-xid"
version = "0.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicode-xid"
version = "0.2.0"
@@ -344,13 +411,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum failure_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "030a733c8287d6213886dd487564ff5c8f6aae10278b3588ed177f9d18f8d231"
"checksum getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
"checksum hermit-abi 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "725cf19794cf90aa94e65050cb4191ff5d8fa87a498383774c47b332e3af952e"
"checksum hexf 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e54653cc32d838771a36532647afad59c4bf7155745eeeec406f71fd5d7e7538"
"checksum hexf-impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "22eadcfadba76a730b2764eaa577d045f35e0ef5174b9c5b46adf1ee42b85e12"
"checksum hexf-parse 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "79296f72d53a89096cbc9a88c9547ee8dfe793388674620e2207593d370550ac"
"checksum itertools 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
"checksum lang-c 0.8.0 (git+https://github.com/kaist-cp/lang-c)" = "<none>"
"checksum libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)" = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0"
"checksum num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
"checksum ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "18869315e81473c951eb56ad5558bbc56978562d3ecfb87abb7a1e944cea4518"
"checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b"
"checksum proc-macro-hack 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b773f824ff2a495833f85fcdddcf85e096949971decada2e93249fa2c6c3d32f"
"checksum proc-macro-hack-impl 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0f674ccc446da486175527473ec8aa064f980b0966bbf767ee743a5dff6244a7"
"checksum proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "df246d292ff63439fea9bc8c0a270bed0e390d5ebd4db4ba15aba81111b5abe3"
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
"checksum quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f"
"checksum rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
"checksum rand_chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
@@ -360,11 +433,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e"
"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
"checksum syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03"
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
"checksum synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545"
"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
"checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
"checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"

View File

@@ -31,3 +31,4 @@ itertools = "0.9.0"
failure = "0.1.7"
tempfile = "3.1.0"
ordered-float = "1.0"
hexf = "0.1.0"

8
Jenkinsfile vendored
View File

@@ -35,8 +35,12 @@ pipeline {
stage('Test') {
steps {
setupRust()
sh "cargo test"
sh "cargo test --release"
// When `cargo test` runs, the function `it_works()` is called in a new thread.
// The stack size of a new thread is `2 MiB` on Linux, and this small stack size
// can cause `stack-overflow` error when testing stack-intensive code.
// For this reason, we need to increase the default size of stack to `4 MiB`.
sh "RUST_MIN_STACK=4194304 cargo test"
sh "RUST_MIN_STACK=4194304 cargo test --release"
}
}
}

18
examples/cmp.c Normal file
View File

@@ -0,0 +1,18 @@
int int_greater_than(int i, unsigned int j) {
if (i > j) return 1;
else return 0;
}
int char_greater_than(char i, unsigned char j) {
if (i > j) return 1;
else return 0;
}
int main() {
// cmp ugt
int r1 = int_greater_than(-1, 1);
// cmp sgt
int r2 = char_greater_than(-1, 1);
return r1 == 1 && r2 == 0;
}

View File

@@ -217,7 +217,7 @@ impl AssertSupported for Declarator {
fn assert_supported(&self) {
self.kind.assert_supported();
self.derived.assert_supported();
self.extensions.is_empty();
assert!(self.extensions.is_empty());
}
}
@@ -282,7 +282,7 @@ impl AssertSupported for ParameterDeclaration {
fn assert_supported(&self) {
self.specifiers.assert_supported();
self.declarator.assert_supported();
self.extensions.is_empty();
assert!(self.extensions.is_empty());
}
}

View File

@@ -23,7 +23,7 @@ pub trait HasDtype {
#[derive(Default)]
struct BaseDtype {
scalar: Option<ast::TypeSpecifier>,
size_modifiers: Option<ast::TypeSpecifier>,
size_modifier: Option<ast::TypeSpecifier>,
signed_option: Option<ast::TypeSpecifier>,
typedef_name: Option<String>,
is_const: bool,
@@ -129,12 +129,12 @@ impl BaseDtype {
self.scalar = Some(type_specifier.clone());
}
ast::TypeSpecifier::Short | ast::TypeSpecifier::Long => {
if self.size_modifiers.is_some() {
if self.size_modifier.is_some() {
return Err(DtypeError::Misc {
message: "two or more size modifiers in declaration specifiers".to_string(),
});
}
self.size_modifiers = Some(type_specifier.clone());
self.size_modifier = Some(type_specifier.clone());
}
ast::TypeSpecifier::TypedefName(identifier) => {
if self.typedef_name.is_some() {
@@ -277,7 +277,7 @@ impl TryFrom<BaseDtype> for Dtype {
fn try_from(spec: BaseDtype) -> Result<Self, DtypeError> {
assert!(
!(spec.scalar.is_none()
&& spec.size_modifiers.is_none()
&& spec.size_modifier.is_none()
&& spec.signed_option.is_none()
&& spec.typedef_name.is_none()
&& !spec.is_const),
@@ -313,19 +313,19 @@ impl TryFrom<BaseDtype> for Dtype {
};
// Applies size modifier
if let Some(size_modifiers) = spec.size_modifiers {
if let Some(size_modifier) = spec.size_modifier {
if dtype != Self::INT {
return Err(DtypeError::Misc {
message: "size modifier can only be used with `int`".to_string(),
});
}
dtype = match size_modifiers {
dtype = match size_modifier {
ast::TypeSpecifier::Short => Self::SHORT,
ast::TypeSpecifier::Long => Self::LONG,
_ => panic!(
"Dtype::try_from::<BaseDtype>: {:?} is not a size modifier",
size_modifiers
size_modifier
),
}
}
@@ -341,6 +341,13 @@ impl TryFrom<BaseDtype> for Dtype {
),
};
if dtype.get_int_width().is_none() {
return Err(DtypeError::Misc {
message: "`signed` and `unsigned` only be applied to `Dtype::Int`"
.to_string(),
});
}
dtype = dtype.set_signed(is_signed);
}
@@ -662,12 +669,18 @@ impl Dtype {
self.with_ast_array_size(&array_decl.node.size)?
}
ast::DerivedDeclarator::Function(func_decl) => {
let params = func_decl
let mut params = func_decl
.node
.parameters
.iter()
.map(|p| Self::try_from(&p.node))
.collect::<Result<Vec<_>, _>>()?;
// If function parameter is (void), remove it
if params.len() == 1 && params[0] == Dtype::unit() {
let _ = params.pop();
}
Self::function(self, params)
}
ast::DerivedDeclarator::KRFunction(kr_func_decl) => {
@@ -758,16 +771,6 @@ impl Dtype {
Ok(dtype)
}
pub fn merge(self, other: Self) -> Result<Self, DtypeError> {
if self == other {
Ok(self)
} else {
Err(DtypeError::Misc {
message: format!("Dtype::merge({:?}, {:?}) failed", self, other),
})
}
}
}
impl fmt::Display for Dtype {

View File

@@ -286,27 +286,31 @@ mod calculator {
ast::BinaryOperator::Modulo => Ok(Value::int(lhs % rhs, lhs_w, lhs_s)),
ast::BinaryOperator::Equals => {
let result = if lhs == rhs { 1 } else { 0 };
Ok(Value::int(result, 1, lhs_s))
Ok(Value::int(result, 1, false))
}
ast::BinaryOperator::NotEquals => {
let result = if lhs != rhs { 1 } else { 0 };
Ok(Value::int(result, 1, lhs_s))
Ok(Value::int(result, 1, false))
}
ast::BinaryOperator::Less => {
// TODO: consider signed option
let result = if lhs < rhs { 1 } else { 0 };
Ok(Value::int(result, 1, lhs_s))
Ok(Value::int(result, 1, false))
}
ast::BinaryOperator::Greater => {
// TODO: consider signed option
let result = if lhs > rhs { 1 } else { 0 };
Ok(Value::int(result, 1, lhs_s))
Ok(Value::int(result, 1, false))
}
ast::BinaryOperator::LessOrEqual => {
// TODO: consider signed option
let result = if lhs <= rhs { 1 } else { 0 };
Ok(Value::int(result, 1, lhs_s))
Ok(Value::int(result, 1, false))
}
ast::BinaryOperator::GreaterOrEqual => {
// TODO: consider signed option
let result = if lhs >= rhs { 1 } else { 0 };
Ok(Value::int(result, 1, lhs_s))
Ok(Value::int(result, 1, false))
}
ast::BinaryOperator::LogicalAnd => {
assert!(lhs < 2);

View File

@@ -5,6 +5,7 @@ mod write_ir;
use core::convert::TryFrom;
use core::fmt;
use core::ops::{Deref, DerefMut};
use hexf::{parse_hexf32, parse_hexf64};
use lang_c::ast;
use ordered_float::OrderedFloat;
use std::collections::HashMap;
@@ -504,23 +505,44 @@ impl TryFrom<&ast::Constant> for Constant {
}
.set_signed(is_signed);
let pat = match integer.base {
ast::IntegerBase::Decimal => Self::DECIMAL,
ast::IntegerBase::Octal => Self::OCTAL,
ast::IntegerBase::Hexadecimal => Self::HEXADECIMAL,
};
let value = if is_signed {
integer.number.parse::<i128>().unwrap() as u128
i128::from_str_radix(integer.number.deref(), pat).unwrap() as u128
} else {
integer.number.parse::<u128>().unwrap()
u128::from_str_radix(integer.number.deref(), pat).unwrap()
};
Ok(Self::int(value, dtype))
}
ast::Constant::Float(float) => {
let pat = match float.base {
ast::FloatBase::Decimal => Self::DECIMAL,
ast::FloatBase::Hexadecimal => Self::HEXADECIMAL,
};
let (dtype, value) = match float.suffix.format {
ast::FloatFormat::Float => {
// Casting from an f32 to an f64 is perfect and lossless (f32 -> f64)
// https://doc.rust-lang.org/stable/reference/expressions/operator-expr.html#type-cast-expressions
(Dtype::FLOAT, float.number.parse::<f32>().unwrap() as f64)
let value = if pat == Self::DECIMAL {
float.number.parse::<f32>().unwrap() as f64
} else {
parse_hexf32(float.number.deref(), false).unwrap() as f64
};
(Dtype::FLOAT, value)
}
ast::FloatFormat::Double => {
(Dtype::DOUBLE, float.number.parse::<f64>().unwrap())
let value = if pat == Self::DECIMAL {
float.number.parse::<f64>().unwrap()
} else {
parse_hexf64(float.number.deref(), false).unwrap()
};
(Dtype::DOUBLE, value)
}
ast::FloatFormat::LongDouble => {
panic!("`FloatFormat::LongDouble` is_unsupported")
@@ -567,6 +589,10 @@ impl TryFrom<&ast::Initializer> for Constant {
}
impl Constant {
const DECIMAL: u32 = 10;
const OCTAL: u32 = 8;
const HEXADECIMAL: u32 = 16;
#[inline]
pub fn is_integer_constant(&self) -> bool {
if let Self::Int { .. } = self {

View File

@@ -57,13 +57,21 @@ pub fn test_irgen(unit: &TranslationUnit, path: &Path) {
.status()
.expect("failed to remove compiled executable");
let ir = Irgen::default()
.translate(unit)
.expect("failed to generate ir");
let ir = match Irgen::default().translate(unit) {
Ok(ir) => ir,
Err(irgen_error) => panic!("{}", irgen_error),
};
let args = Vec::new();
assert_eq!(
ir::interp(&ir, args),
Ok(ir::Value::int(status as u128, 32, true))
);
let result = match ir::interp(&ir, args) {
Ok(result) => result,
Err(interp_error) => panic!("{}", interp_error),
};
let result = if let ir::Value::Int { .. } = &result {
result
} else {
panic!("non-integer value occurs")
};
assert_eq!(result, ir::Value::int(status as u128, 32, true));
}

View File

@@ -36,6 +36,23 @@ REPLACE_DICT = {
"\"g_\w*\", ": "", # transparent_crc에서 프린트 목적으로 받은 StringLiteral 삭제
"char\* vname, ": "", # transparent_crc에서 사용하지 않는 파라미터 삭제
r"[^\n]*_IO_2_1_[^;]*;": "", # extern을 지우면서 생긴 size를 알 수 없는 struct 삭제
r"__asm\s*\([^\)]*\)": "", # asm extension in mac
r"__asm__\s*\([^\)]*\)": "", # asm extension in linux
# To check fuzzer before make kecc support struct type
"struct[^}]*};": "",
" struct[^{]*[^}]*}[^;]*;": "",
"typedef struct _IO_FILE __FILE;": "",
"struct _IO_FILE;": "",
"typedef struct _IO_FILE FILE;": "typedef int FILE;",
"typedef struct _IO_FILE": "typedef int",
"typedef struct __locale_struct": "typedef int",
"typedef __locale_t locale_t;": "typedef int locale_t;",
"struct _IO_FILE_plus;": "",
"typedef _G_fpos_t": "typedef int",
"typedef struct[^\n]*\n{[^}]*}[^;]*;": "",
"typedef struct[^{]{[^}]*}": "typedef int",
"struct _IO_FILE": "int",
}
CSMITH_DIR = "csmith-2.3.0"