Skip to content

Commit e9e8d05

Browse files
committed
Rewrote statement processing to be better suited for seting non-trivial places(memory locations at adress of pointer, seting flelds of a struct that is a member of another one, etc.)
1 parent 6358536 commit e9e8d05

File tree

6 files changed

+389
-131
lines changed

6 files changed

+389
-131
lines changed

src/assigment_target.rs

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
use crate::{clr_method::LocalPlacement, BaseIR, CLRMethod,VariableType};
2+
use rustc_middle::mir::Rvalue as CompilerRValue;
3+
use rustc_middle::mir::interpret::{Scalar,ConstValue};
4+
use rustc_middle::{
5+
mir::{Body, Place,AggregateKind,CastKind,BinOp,Operand,ConstantKind},
6+
ty::TyCtxt,
7+
};
8+
macro_rules! sign_cast {
9+
($var:ident,$src:ty,$dest:ty) => {
10+
(<$dest>::from_ne_bytes(($var as $src).to_ne_bytes()))
11+
};
12+
}
13+
enum AsigmentValuePosition {
14+
BeforeAdress,
15+
AfterAdress,
16+
}
17+
pub(crate) struct AsigmentTarget {
18+
adress_calc: Vec<BaseIR>,
19+
value_pos: AsigmentValuePosition,
20+
set_ops: Vec<BaseIR>,
21+
}
22+
impl AsigmentTarget {
23+
pub(crate) fn from_placement(place: Place, clr_method: &CLRMethod) -> Self {
24+
let mut new = Self {
25+
adress_calc: Vec::new(),
26+
set_ops: Vec::new(),
27+
value_pos: AsigmentValuePosition::BeforeAdress,
28+
};
29+
if place.projection.is_empty() {
30+
let local: u32 = place.local.into();
31+
new.set_ops
32+
.push(match clr_method.local_id_placement(local) {
33+
LocalPlacement::Arg(arg_id) => BaseIR::STArg(arg_id),
34+
LocalPlacement::Var(var_id) => BaseIR::STLoc(var_id),
35+
});
36+
} else {
37+
panic!("Can't handle non-trivial assignments!");
38+
}
39+
new
40+
}
41+
pub(crate) fn finalize(self, rvalue: RValue, clr_method: &mut CLRMethod) {
42+
match self.value_pos{
43+
AsigmentValuePosition::BeforeAdress => {
44+
clr_method.extend_ops(rvalue.get_ops());
45+
clr_method.extend_ops(&self.adress_calc);
46+
clr_method.extend_ops(&self.set_ops);
47+
},
48+
AsigmentValuePosition::AfterAdress => {
49+
clr_method.extend_ops(&self.adress_calc);
50+
clr_method.extend_ops(rvalue.get_ops());
51+
clr_method.extend_ops(&self.set_ops);
52+
},
53+
}
54+
}
55+
}
56+
pub(crate) struct RValue {
57+
ops:Vec<BaseIR>,
58+
}
59+
impl RValue {
60+
pub(crate) fn get_ops(&self)->&[BaseIR]{
61+
&self.ops
62+
}
63+
pub(crate) fn from_rvalue<'ctx>(
64+
rvalue: &CompilerRValue<'ctx>,
65+
body: &Body<'ctx>,
66+
tyctx: &TyCtxt<'ctx>,
67+
clr_method:&CLRMethod,
68+
) -> Self {
69+
let mut new = Self {ops:Vec::new()};
70+
new.process_rvalue(rvalue, body, tyctx,clr_method);
71+
new
72+
}
73+
fn process_binop(&mut self,binop: BinOp, a: &Operand, b: &Operand,clr_method:&CLRMethod) {
74+
self.process_operand(a,clr_method);
75+
self.process_operand(b,clr_method);
76+
self.ops.push(match binop {
77+
BinOp::Add => BaseIR::Add,
78+
BinOp::Sub => BaseIR::Sub,
79+
BinOp::Mul => BaseIR::Mul,
80+
BinOp::Shl => BaseIR::Shl,
81+
BinOp::Shr => BaseIR::Shr,
82+
BinOp::Eq => BaseIR::Eq,
83+
BinOp::Ne => BaseIR::NEq,
84+
BinOp::Gt => BaseIR::Gt,
85+
BinOp::Rem => BaseIR::Rem,
86+
BinOp::BitXor => BaseIR::Xor,
87+
BinOp::BitOr => BaseIR::Or,
88+
BinOp::BitAnd => BaseIR::And,
89+
BinOp::Div => BaseIR::Div,
90+
_ => todo!("Unknown binop:{binop:?}"),
91+
});
92+
}
93+
fn process_rvalue<'ctx>(
94+
&mut self,
95+
rvalue: &CompilerRValue<'ctx>,
96+
body: &Body<'ctx>,
97+
tyctx: &TyCtxt<'ctx>,
98+
clr_method:&CLRMethod,
99+
) {
100+
match rvalue {
101+
CompilerRValue::Use(operand) => self.process_operand(operand,clr_method),
102+
CompilerRValue::BinaryOp(binop, operands) => {
103+
let (a, b): (_, _) = (&operands.0, &operands.1);
104+
self.process_binop(*binop,a,b,clr_method);
105+
}
106+
CompilerRValue::Cast(
107+
CastKind::IntToInt
108+
| CastKind::FloatToFloat
109+
| CastKind::FloatToInt
110+
| CastKind::IntToFloat,
111+
operand,
112+
target,
113+
) => {
114+
self.process_operand(operand,clr_method);
115+
self.convert(
116+
&VariableType::from_ty(operand.ty(body, *tyctx)),
117+
&VariableType::from_ty(*target),
118+
);
119+
}
120+
CompilerRValue::Aggregate(kind, operands) => {
121+
match kind.as_ref() {
122+
AggregateKind::Adt(def_id, variant_idx, subst_ref, utai, fidx) => {
123+
//let (def_id,variant_idx,subst_ref,utai,fidx) = *adt;
124+
panic!("def_id:{def_id:?},variant_idx:{variant_idx:?},subst_ref:{subst_ref:?},utai:{utai:?},fidx:{fidx:?}");
125+
}
126+
_ => todo!(
127+
"Can't yet handle the aggregate of kind {kind:?} and operands:{operands:?}"
128+
),
129+
}
130+
}
131+
_ => todo!("Can't yet handle a rvalue of type {rvalue:?}"),
132+
}
133+
}
134+
fn process_constant(&mut self, constant: ConstantKind,clr_method:&CLRMethod) {
135+
match constant {
136+
ConstantKind::Val(value, r#type) => match value {
137+
ConstValue::Scalar(scalar) => {
138+
let value: u128 = if let Scalar::Int(scalar) = scalar {
139+
scalar
140+
.try_to_uint(scalar.size())
141+
.expect("IMPOSSIBLE. Size of scalar was not equal to itself.")
142+
} else {
143+
panic!("Can't support pointers quite yet!");
144+
};
145+
self.load_constant_primitive(&VariableType::from_ty(r#type), value);
146+
}
147+
_ => todo!("Unhanled constant value {value:?}"),
148+
},
149+
_ => todo!("Unhanled constant {constant:?}"),
150+
};
151+
}
152+
// Makes so the top of the stack is the value of RValue
153+
fn process_operand(&mut self, operand: &Operand,clr_method:&CLRMethod) {
154+
match operand {
155+
Operand::Copy(place) => self.load(place.local.into(),clr_method),
156+
//TODO:Do moves need to be treated any diffrently forom copies in the context of CLR?
157+
Operand::Move(place) => self.load(place.local.into(),clr_method),
158+
Operand::Constant(const_val) => {
159+
self.process_constant(const_val.literal,clr_method);
160+
}
161+
}
162+
}
163+
fn load_constant_primitive(&mut self, var_type: &VariableType, value: u128) {
164+
match var_type {
165+
VariableType::I8 => self.ops.push(BaseIR::LDConstI8(sign_cast!(value, u8, i8))),
166+
VariableType::I32 => self
167+
.ops
168+
.push(BaseIR::LDConstI32(sign_cast!(value, u32, i32))),
169+
VariableType::I64 => self
170+
.ops
171+
.push(BaseIR::LDConstI64(sign_cast!(value, u64, i64))),
172+
VariableType::Bool => self.ops.push(BaseIR::LDConstI8((value != 0) as u8 as i8)),
173+
_ => todo!("Can't yet load constant primitives of type {var_type:?}!"),
174+
}
175+
}
176+
fn convert(&mut self, src: &VariableType, dest: &VariableType) {
177+
match (src, dest) {
178+
(
179+
VariableType::F32
180+
| VariableType::I8
181+
| VariableType::I16
182+
| VariableType::I32
183+
| VariableType::U8
184+
| VariableType::U16
185+
| VariableType::U32,
186+
VariableType::I32,
187+
) => self.ops.push(BaseIR::ConvI32),
188+
(
189+
VariableType::F64
190+
| VariableType::I64
191+
| VariableType::U64
192+
| VariableType::ISize
193+
| VariableType::USize,
194+
VariableType::I32,
195+
) => self.ops.push(BaseIR::ConvI32Checked),
196+
(VariableType::F32, VariableType::I8) => self.ops.push(BaseIR::ConvI8),
197+
(VariableType::I32, VariableType::F32) => self.ops.push(BaseIR::ConvF32),
198+
_ => todo!("Can't convert type {src:?} to {dest:?}"),
199+
}
200+
}
201+
fn load(&mut self, local: u32,clr_method:&CLRMethod) {
202+
self.ops.push(match clr_method.local_id_placement(local) {
203+
LocalPlacement::Arg(arg_id) => BaseIR::LDArg(arg_id),
204+
LocalPlacement::Var(var_id) => BaseIR::LDLoc(var_id),
205+
})
206+
}
207+
}

src/base_ir.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ pub(crate) enum BaseIR {
66
LDConstI8(i8),
77
LDConstI32(i32),
88
LDConstI64(i64),
9+
STIInd(u8),
910
LDConstString(String),
1011
STArg(u32),
1112
LDArg(u32),
@@ -34,9 +35,7 @@ pub(crate) enum BaseIR {
3435
BBLabel { bb_id: u32 },
3536
BEq { target: u32 },
3637
GoTo { target: u32 },
37-
NewObj{
38-
ctor_fn:String,
39-
},
38+
NewObj { ctor_fn: String },
4039
Throw,
4140
}
4241
impl BaseIR {
@@ -73,8 +72,9 @@ impl BaseIR {
7372
Self::ConvI32Checked => "\tconv.ovf.i4\n".into(),
7473
Self::Nop => "\tnop\n".into(), //_=>format!("\t//Comment!\n"),
7574
Self::LDConstString(string) => format!("\tldstr \"{string}\"\n"),
76-
Self::NewObj{ctor_fn} => format!("\tnewobj instance {ctor_fn}\n"),
77-
Self::Throw => "\tthrow\n".into(),
75+
Self::NewObj { ctor_fn } => format!("\tnewobj instance {ctor_fn}\n"),
76+
Self::Throw => "\tthrow\n".into(),
77+
Self::STIInd(size) => format!("\tstind.i{size}\n"),
7878
}
7979
.into()
8080
}

0 commit comments

Comments
 (0)