Add skeleton for arrays in IR

This commit is contained in:
Jeehoon Kang
2020-04-01 23:44:37 +09:00
parent 93a1d767a5
commit cef3fb7650
8 changed files with 95 additions and 11 deletions

View File

@@ -1,9 +1,19 @@
int sum(int len, int p[2][3]) {
return 0;
int sum(int len, int *p) {
int result = 0;
for (int i = 0; i < len; i++) {
result += p[i];
}
return result;
}
int main() {
int a[2][3];
int a[5];
int len = 5;
return 0;
for (int i = 0; i < len; i++) {
a[i] = i;
}
return sum(len, a) == 10;
}

16
examples/array2.c Normal file
View File

@@ -0,0 +1,16 @@
void init(int row, int col, int a[4][5]) {
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
a[i][j] = i * j;
}
}
}
int main() {
int a[4][5];
int row = 4, col = 5;
init(row, col, a);
return a[2][3] == 6;
}

13
examples/array3.c Normal file
View File

@@ -0,0 +1,13 @@
int* foo(int a[10]){
return a;
}
int main() {
int a[10];
for (int i = 0; i < 10; i++) {
(foo(a))[i] = i;
}
return a[5] == 5;
}

View File

@@ -729,7 +729,10 @@ impl Dtype {
}
Self::Array { inner, size } => {
let inner = inner.deref().clone().resolve_typedefs(typedefs)?;
Dtype::array(inner, *size)
Dtype::Array {
inner: Box::new(inner),
size: *size,
}
}
Self::Function { ret, params } => {
let ret = ret.deref().clone().resolve_typedefs(typedefs)?;

View File

@@ -950,6 +950,27 @@ impl<'i> State<'i> {
}
})?
}
Instruction::GetElementPtr { ptr, offset, dtype } => {
let ptr = self.interp_operand(ptr.clone())?;
let (value, _, _) = self
.interp_operand(offset.clone())?
.get_int()
.expect("`idx` must be `Value::Int`");
let (bid, prev_offset, ..) = ptr
.get_pointer()
.expect("`pointer` must be `Value::Pointer` to access memory");
let inner_dtype = dtype
.get_pointer_inner()
.expect("`dtype` must be pointer type");
let offset = prev_offset + value as isize;
assert!(0 <= offset);
Value::pointer(*bid, offset as isize, inner_dtype.clone())
}
};
let register = RegisterId::temp(self.stack_frame.pc.bid, self.stack_frame.pc.iid);

View File

@@ -210,6 +210,13 @@ pub enum Instruction {
value: Operand,
target_dtype: Dtype,
},
/// `GetElementPtr` is inspired from `getelementptr` instruction of LLVM.
/// https://llvm.org/docs/LangRef.html#i-getelementptr
GetElementPtr {
ptr: Operand,
offset: Operand,
dtype: Box<Dtype>,
},
}
impl HasDtype for Instruction {
@@ -228,6 +235,7 @@ impl HasDtype for Instruction {
.set_const(false),
Self::Call { return_type, .. } => return_type.clone(),
Self::TypeCast { target_dtype, .. } => target_dtype.clone(),
Self::GetElementPtr { dtype, .. } => dtype.deref().clone(),
}
}
}

View File

@@ -174,6 +174,9 @@ impl WriteString for Instruction {
value,
target_dtype,
} => format!("typecast {} to {}", value.write_string(), target_dtype),
Instruction::GetElementPtr { ptr, offset, .. } => {
format!("getelementptr {} offset {}", ptr, offset)
}
}
}
}

View File

@@ -1,7 +1,7 @@
use lang_c::ast::*;
use std::fs::{self, File};
use std::path::Path;
use std::process::Command;
use std::process::{Command, Stdio};
use tempfile::tempdir;
use crate::*;
@@ -25,17 +25,27 @@ pub fn test_irgen(unit: &TranslationUnit, path: &Path) {
// Check if the file has .c extension
assert_eq!(path.extension(), Some(std::ffi::OsStr::new("c")));
// Test parse
c::Parse::default()
.translate(&path)
.expect("failed to parse the given program");
let file_path = path.display().to_string();
let bin_path = path.with_extension("exe").as_path().display().to_string();
// Compile c file
Command::new("gcc")
// Compile c file: If fails, test is vacuously success
if !Command::new("gcc")
.args(&["-O1", &file_path, "-o", &bin_path])
.output()
.expect("failed to compile the given program");
.stderr(Stdio::null())
.status()
.unwrap()
.success()
{
return;
}
// Execute compiled executable
let status = Command::new(fs::canonicalize(format!("./{}", bin_path.clone())).unwrap())
let status = Command::new(fs::canonicalize(bin_path.clone()).unwrap())
.status()
.expect("failed to execute the compiled executable")
.code()