Skip to content

Commit

Permalink
Merge pull request #340 from uwplse/oflatt-upstream-rs2bril-init
Browse files Browse the repository at this point in the history
[rs2bril] Array initialization using Bril loop instead of unrolling
  • Loading branch information
sampsyo authored Oct 22, 2024
2 parents e9297e9 + 8fc6265 commit 2a9c5bb
Show file tree
Hide file tree
Showing 2 changed files with 150 additions and 5 deletions.
7 changes: 4 additions & 3 deletions bril-rs/rs2bril/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ View the interface with `cargo doc --open` or install with `make install` using
- Automatic static memory management <https://www.cs.cornell.edu/courses/cs6120/2020fa/blog/asmm/> has not been implemented so arrays must be explicitly dropped where `drop` is specialized to translate to a call to free: `drop([0]);`
- For loops, `continue`, `break`, and ranges have not been implemented(but could be).
- Memory is implemented using Rust arrays. These are statically sized values unlike how calls to Bril `alloc` can be dynamically sized. One solution is to just allocate a large enough array and then treat the dynamic size like the length. (A subset of vectors could also be specialized in the future).
- Arrays must be initialized with repetition syntax, which is awkward for nested arrays.
- In normal Rust, `if` can also be used as an expression that evaluates a value to be put in a variable. This is not implemented and it is assumed that there will only be if statements.
- The Bril code that it produces is super inefficient and it is left to other tools to optimize it. Array initialization is unrolled is not an optimal solution.
- The Bril code that it produces is super inefficient and it is left to other tools to optimize it.
- `!=` and automatic promotions of integer literals to floats are not implemented.
- to support indexing into arrays, you can cast to usize in the Rust code. This will be ignored when generating Bril. `arr[i as usize];`
- The parts of Rust which make it valid like lifetimes, references, mutability, and function visibility are ignored and compiled away in Bril.
- To support indexing into arrays, you can cast to usize in the Rust code. This will be ignored when generating Bril. `arr[i as usize];`
- The parts of Rust which make it valid like lifetimes, references, mutability, and function visibility are ignored and compiled away in Bril.
148 changes: 146 additions & 2 deletions bril-rs/rs2bril/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,146 @@ fn from_signature_to_function(
}
}

/// Create and initialize an array containing `num_rep` repetitions of `rep_var`.
fn array_repetition_helper(
rep_var: &String,
num_reps: i64,
mut code: Vec<Code>,
state: &mut State,
) -> (Option<String>, Vec<Code>) {
// make constant one
let one = state.fresh_var(Type::Int);
code.push(Code::Instruction(Instruction::Constant {
dest: one.clone(),
op: ConstOps::Const,
pos: None,
const_type: Type::Int,
value: Literal::Int(1),
}));

let arr_type = Type::Pointer(Box::new(state.get_type_for_ident(rep_var)));
let pointer = state.fresh_var(arr_type.clone());
let size = state.fresh_var(Type::Int);
code.push(Code::Instruction(Instruction::Constant {
dest: size.clone(),
op: ConstOps::Const,
pos: None,
const_type: Type::Int,
value: Literal::Int(num_reps),
}));
code.push(Code::Instruction(Instruction::Value {
args: vec![size.clone()],
dest: pointer.clone(),
funcs: Vec::new(),
labels: Vec::new(),
op: ValueOps::Alloc,
pos: None,
op_type: arr_type.clone(),
}));

// make an index pointer for the array
let current_ptr = state.fresh_var(arr_type.clone());
code.push(Code::Instruction(Instruction::Value {
args: vec![pointer.clone()],
dest: current_ptr.clone(),
funcs: Vec::new(),
labels: Vec::new(),
op: ValueOps::Id,
pos: None,
op_type: arr_type.clone(),
}));

let start_label = state.fresh_label();
let then_label = state.fresh_label();
let end_label = state.fresh_label();

let iter = state.fresh_var(Type::Int);
code.push(Code::Instruction(Instruction::Constant {
dest: iter.clone(),
op: ConstOps::Const,
pos: None,
const_type: Type::Int,
value: Literal::Int(0),
}));

code.push(Code::Label {
label: start_label.clone(),
pos: None,
});

// check if iter < size
let cond_var = state.fresh_var(Type::Bool);
code.push(Code::Instruction(Instruction::Value {
args: vec![iter.clone(), size],
dest: cond_var.clone(),
funcs: Vec::new(),
labels: Vec::new(),
op: ValueOps::Lt,
pos: None,
op_type: Type::Bool,
}));

code.push(Code::Instruction(Instruction::Effect {
args: vec![cond_var],
funcs: Vec::new(),
labels: vec![then_label.clone(), end_label.clone()],
op: EffectOps::Branch,
pos: None,
}));

code.push(Code::Label {
label: then_label,
pos: None,
});

// write var to the current ptr
code.push(Code::Instruction(Instruction::Effect {
args: vec![current_ptr.clone(), rep_var.clone()],
funcs: Vec::new(),
labels: Vec::new(),
op: EffectOps::Store,
pos: None,
}));

// increment current ptr
code.push(Code::Instruction(Instruction::Value {
args: vec![current_ptr.clone(), one.clone()],
dest: current_ptr,
funcs: Vec::new(),
labels: Vec::new(),
op: ValueOps::PtrAdd,
pos: None,
op_type: arr_type,
}));

// increment iter
code.push(Code::Instruction(Instruction::Value {
args: vec![iter.clone(), one],
dest: iter,
funcs: Vec::new(),
labels: Vec::new(),
op: ValueOps::Add,
pos: None,
op_type: Type::Int,
}));

// jump to start label
code.push(Code::Instruction(Instruction::Effect {
args: Vec::new(),
funcs: Vec::new(),
labels: vec![start_label],
op: EffectOps::Jump,
pos: None,
}));

code.push(Code::Label {
label: end_label,
pos: None,
});

(Some(pointer), code)
}

fn array_init_helper(
vars: Vec<String>,
mut code: Vec<Code>,
Expand Down Expand Up @@ -909,8 +1049,12 @@ fn from_expr_to_bril(expr: Expr, state: &mut State) -> (Option<String>, Vec<Code
_ => panic!("can't handle non-literal Int for repeated array length"),
};

let vars = std::iter::repeat(var.unwrap()).take(array_len).collect();
array_init_helper(vars, code, state)
array_repetition_helper(
&var.unwrap(),
i64::try_from(array_len).unwrap(),
code,
state,
)
}
Expr::Return(ExprReturn {
attrs,
Expand Down

0 comments on commit 2a9c5bb

Please sign in to comment.