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]) {
|
||||
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;
|
||||
|
||||
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 } => {
|
||||
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)?;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
22
src/tests.rs
22
src/tests.rs
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user