Skip to content

Commit d064308

Browse files
committed
Local types are now propely resolved
1 parent 9de913a commit d064308

File tree

4 files changed

+93
-11
lines changed

4 files changed

+93
-11
lines changed

src/assembly.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ pub(crate) struct Assembly {
99
name: IString,
1010
}
1111
impl Assembly {
12+
1213
pub(crate) fn into_il_ir(&self) -> IString {
1314
let mut methods = String::new();
1415
for method in &self.methods{
@@ -45,7 +46,8 @@ impl Assembly {
4546
None => (),
4647
}
4748
}
48-
clr_method.opt();
49+
// Optimization is currently broken, and may produce invalid IR.
50+
//clr_method.opt();
4951
clr_method.typecheck();
5052
println!("clr_method:{clr_method:?}");
5153
println!("instance:{instance:?}\n");

src/base_ir.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,22 @@ pub(crate) enum BaseIR {
1212
Return,
1313
}
1414
impl BaseIR{
15-
pub(crate) fn get_trivial_type(&self,parrent_method:&CLRMethod)->Option<VariableType>{
15+
pub(crate) fn stack_change(&self)->i8{
16+
match self{
17+
Self::Add | Self::Mul | Self::Shl=>-1,
18+
Self::Return=>-1,
19+
Self::LDLoc(_)=>1,
20+
Self::LDArg(_)=>1,
21+
Self::STLoc(_)=>-1,
22+
Self::STArg(_)=>-1,
23+
Self::LDConstI32(_)=>-1,
24+
}
25+
}
26+
pub(crate) fn get_trivial_type(&self,parent_method:&CLRMethod)->Option<VariableType>{
1627
match self{
1728
Self::LDConstI32(_)=>Some(VariableType::I32),
18-
Self::LDArg(arg_id)=>Some(parrent_method.get_arg_type(*arg_id).clone()),
29+
Self::LDLoc(var_id)=>parent_method.local_type(*var_id).cloned(),
30+
Self::LDArg(arg_id)=>Some(parent_method.get_arg_type(*arg_id).clone()),
1931
_=>None,
2032
}
2133
}
@@ -28,7 +40,7 @@ impl BaseIR{
2840
Self::Add=>"\tadd\n".into(),
2941
Self::Mul=>"\tmul\n".into(),
3042
Self::Shl=>"\tshl\n".into(),
31-
Self::LDConstI32(i32const)=>format!("ldc.i4 {i32const}\t\n"),
43+
Self::LDConstI32(i32const)=>format!("\tldc.i4 {i32const}\t\n"),
3244
_=>format!("\t//Comment!\n"),
3345
}.into()
3446
}

src/clr_method.rs

Lines changed: 64 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,25 @@ enum LocalPlacement {
2323
}
2424
impl CLRMethod {
2525
fn name(&self)->&str{&self.name}
26+
fn crosses_bb_border(&self,start:usize,end:usize)->bool{
27+
false
28+
}
29+
fn backtrace_op_type(&self,op_pos:usize)->Option<&VariableType>{
30+
let mut op_pos:isize = (op_pos as isize - 1);
31+
let mut depth = -1;
32+
while op_pos >= 0{
33+
depth += self.ops[op_pos as usize].stack_change();
34+
if(depth == 0){
35+
return self.op_types[op_pos as usize].as_ref();
36+
}
37+
op_pos -= 1;
38+
}
39+
None
40+
}
41+
// This function returns the type of a local variable if it is known
42+
pub(crate) fn local_type(&self,local:u32)->Option<&VariableType>{
43+
self.locals.get(local as usize)?.as_ref()
44+
}
2645
pub(crate) fn get_arg_type(&self,arg:u32)->&VariableType{
2746
&self.sig.inputs()[arg as usize]
2847
}
@@ -33,14 +52,52 @@ impl CLRMethod {
3352
}
3453
}
3554
}
55+
fn set_local_types(&mut self){
56+
for index in 0..(self.op_types.len()){
57+
if let BaseIR::STLoc(index) = self.ops[index as usize]{
58+
if let Some(var_type) = &self.op_types[index as usize]{
59+
while self.locals.len() < index as usize + 1{self.locals.push(None)};
60+
self.locals[index as usize] = Some(var_type.clone());
61+
}
62+
}
63+
}
64+
}
65+
fn backtrace_types(&mut self){
66+
for index in 0..(self.op_types.len()){
67+
if let None = self.op_types[index]{
68+
self.op_types[index] = self.backtrace_op_type(index).cloned();
69+
}
70+
}
71+
}
3672
pub(crate) fn typecheck(&mut self){
3773
while self.op_types.len() < self.ops.len(){
3874
self.op_types.push(None);
3975
}
40-
41-
self.set_trivial_types();
76+
for _ in 0..0x100{
77+
self.set_trivial_types();
78+
self.backtrace_types();
79+
self.set_local_types();
80+
if self.op_types.iter().all(|t| t.is_some()){break;}
81+
}
4282
println!("op_types:{:?}",self.op_types);
4383
}
84+
pub(crate) fn locals_init(&self)->IString{
85+
if self.locals.is_empty(){
86+
return "".into();
87+
}
88+
let mut locals = String::new();
89+
let mut locals_iter = self.locals.iter().enumerate();
90+
match locals_iter.next(){
91+
Some((index,first))=>{
92+
locals.push_str(&format!("\n\t\t[{index}] {loc_type}",loc_type = first.as_ref().expect("UNRESOLVED LOCAL DURING IL EMISSION!").il_name()))
93+
}
94+
None=>(),
95+
}
96+
for (index,local) in locals_iter{
97+
locals.push_str(&format!(",\n\t\t[{index}] {loc_type}",loc_type = local.as_ref().expect("UNRESOLVED LOCAL DURING IL EMISSION!").il_name()))
98+
}
99+
format!("\t.locals init({locals}\n\t)").into()
100+
}
44101
pub(crate) fn into_il_ir(&self)->String{
45102
let output = self.sig.output().il_name();
46103
let mut arg_list = String::new();
@@ -57,20 +114,20 @@ impl CLRMethod {
57114
for op in &self.ops{
58115
ops_ir.push_str(&op.clr_ir());
59116
}
60-
format!(".method public static {output} {name}({arg_list}){{\n{ops_ir}}}\n",name = self.name())
117+
format!(".method public static {output} {name}({arg_list}){{\n{locals_init}\n{ops_ir}}}\n",name = self.name(),locals_init = self.locals_init())
61118
}
62119
fn argc(&self) -> u32 {
63120
self.sig.inputs().len() as u32
64121
}
65122
fn remove_sl(&mut self) -> usize {
66123
let mut opt_ops: Vec<BaseIR> = Vec::with_capacity(self.ops.len());
67-
let mut ops_peek = self.ops.iter().peekable();
68-
while let Some(op) = ops_peek.next() {
124+
let mut ops_peek = self.ops.iter().enumerate().peekable();
125+
while let Some((index,op)) = ops_peek.next() {
69126
match op {
70127
BaseIR::STLoc(local_id) => {
71-
if let Some(BaseIR::LDLoc(other_id)) = ops_peek.peek() {
128+
if let Some((next_index,BaseIR::LDLoc(other_id))) = ops_peek.peek() {
72129
//Ops store and the load the same value, being effectively a NOP.
73-
if local_id == other_id {
130+
if local_id == other_id && !self.crosses_bb_border(index,*next_index) {
74131
ops_peek.next();
75132
continue;
76133
}

test/identity.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,17 @@ pub extern fn add(a:i32)->i32{a+a}
33
pub extern fn add2(a:i32,b:i32)->i32{a + b}
44
pub extern fn sqr_mag(ax:i32,ay:i32)->i32{ax*ax + ay*ay}
55
pub extern fn pow2(power:i32)->i32{1<<power}
6+
/*
7+
pub extern fn factorial(mut n:i32)->i32{
8+
let mut factorial = 1;
9+
while n > 1{
10+
factorial *= n;
11+
n-=1;
12+
}
13+
//for x in 0..100{}
14+
factorial
15+
}*/
16+
//pub extern fn call_pow2(power:i32)->i32{ let val = pow2(power); val}
617
struct Vector3{x:f32,y:f32,z:f32}
718
/*
819
impl std::ops::Add for Vector3{

0 commit comments

Comments
 (0)