mirror of
https://github.com/kmc7468/cs420.git
synced 2025-12-14 22:38:46 +00:00
Add skeleton for arrays in IR
This commit is contained in:
@@ -1,9 +1,19 @@
|
|||||||
int sum(int len, int p[2][3]) {
|
int sum(int len, int *p) {
|
||||||
return 0;
|
int result = 0;
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
result += p[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
int a[2][3];
|
int a[5];
|
||||||
|
int len = 5;
|
||||||
|
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
a[i] = i;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return sum(len, a) == 10;
|
||||||
}
|
}
|
||||||
|
|||||||
16
examples/array2.c
Normal file
16
examples/array2.c
Normal 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
13
examples/array3.c
Normal 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;
|
||||||
|
}
|
||||||
@@ -729,7 +729,10 @@ impl Dtype {
|
|||||||
}
|
}
|
||||||
Self::Array { inner, size } => {
|
Self::Array { inner, size } => {
|
||||||
let inner = inner.deref().clone().resolve_typedefs(typedefs)?;
|
let inner = inner.deref().clone().resolve_typedefs(typedefs)?;
|
||||||
Dtype::array(inner, *size)
|
Dtype::Array {
|
||||||
|
inner: Box::new(inner),
|
||||||
|
size: *size,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Self::Function { ret, params } => {
|
Self::Function { ret, params } => {
|
||||||
let ret = ret.deref().clone().resolve_typedefs(typedefs)?;
|
let ret = ret.deref().clone().resolve_typedefs(typedefs)?;
|
||||||
|
|||||||
@@ -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);
|
let register = RegisterId::temp(self.stack_frame.pc.bid, self.stack_frame.pc.iid);
|
||||||
|
|||||||
@@ -210,6 +210,13 @@ pub enum Instruction {
|
|||||||
value: Operand,
|
value: Operand,
|
||||||
target_dtype: Dtype,
|
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 {
|
impl HasDtype for Instruction {
|
||||||
@@ -228,6 +235,7 @@ impl HasDtype for Instruction {
|
|||||||
.set_const(false),
|
.set_const(false),
|
||||||
Self::Call { return_type, .. } => return_type.clone(),
|
Self::Call { return_type, .. } => return_type.clone(),
|
||||||
Self::TypeCast { target_dtype, .. } => target_dtype.clone(),
|
Self::TypeCast { target_dtype, .. } => target_dtype.clone(),
|
||||||
|
Self::GetElementPtr { dtype, .. } => dtype.deref().clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -174,6 +174,9 @@ impl WriteString for Instruction {
|
|||||||
value,
|
value,
|
||||||
target_dtype,
|
target_dtype,
|
||||||
} => format!("typecast {} to {}", value.write_string(), target_dtype),
|
} => format!("typecast {} to {}", value.write_string(), target_dtype),
|
||||||
|
Instruction::GetElementPtr { ptr, offset, .. } => {
|
||||||
|
format!("getelementptr {} offset {}", ptr, offset)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
22
src/tests.rs
22
src/tests.rs
@@ -1,7 +1,7 @@
|
|||||||
use lang_c::ast::*;
|
use lang_c::ast::*;
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::process::Command;
|
use std::process::{Command, Stdio};
|
||||||
use tempfile::tempdir;
|
use tempfile::tempdir;
|
||||||
|
|
||||||
use crate::*;
|
use crate::*;
|
||||||
@@ -25,17 +25,27 @@ pub fn test_irgen(unit: &TranslationUnit, path: &Path) {
|
|||||||
// Check if the file has .c extension
|
// Check if the file has .c extension
|
||||||
assert_eq!(path.extension(), Some(std::ffi::OsStr::new("c")));
|
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 file_path = path.display().to_string();
|
||||||
let bin_path = path.with_extension("exe").as_path().display().to_string();
|
let bin_path = path.with_extension("exe").as_path().display().to_string();
|
||||||
|
|
||||||
// Compile c file
|
// Compile c file: If fails, test is vacuously success
|
||||||
Command::new("gcc")
|
if !Command::new("gcc")
|
||||||
.args(&["-O1", &file_path, "-o", &bin_path])
|
.args(&["-O1", &file_path, "-o", &bin_path])
|
||||||
.output()
|
.stderr(Stdio::null())
|
||||||
.expect("failed to compile the given program");
|
.status()
|
||||||
|
.unwrap()
|
||||||
|
.success()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Execute compiled executable
|
// 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()
|
.status()
|
||||||
.expect("failed to execute the compiled executable")
|
.expect("failed to execute the compiled executable")
|
||||||
.code()
|
.code()
|
||||||
|
|||||||
Reference in New Issue
Block a user