Skip to content

Commit 3612d55

Browse files
committed
Simple functions may now be converted into IR
1 parent 9ecc6e7 commit 3612d55

File tree

3 files changed

+149
-24
lines changed

3 files changed

+149
-24
lines changed

makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ RUSTC = rustc
44
RUST_FLAGS = --crate-type lib
55
test: build_backend compile_simple_file
66
compile_simple_file:
7-
rustc $(RUST_FLAGS) -Z codegen-backend=$(CODEGEN_BACKEND) test/identity.rs
7+
rustc $(RUST_FLAGS) -O -Z codegen-backend=$(CODEGEN_BACKEND) test/identity.rs
88
build_backend:
99
cargo build
1010

src/lib.rs

Lines changed: 139 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,73 +10,190 @@ extern crate rustc_driver;
1010
use rustc_codegen_ssa::CrateInfo;
1111
use std::any::Any;
1212
use rustc_codegen_ssa::{traits::CodegenBackend,CodegenResults};
13-
use rustc_middle::{ty::{TyCtxt,Ty,ParamEnv,Instance,PolyFnSig},dep_graph::{WorkProductId,WorkProduct},mir::{Statement,StatementKind,Rvalue,mono::MonoItem,Operand}};
13+
use rustc_middle::{ty::{TyCtxt,Ty,ParamEnv,Instance,PolyFnSig,TyKind,IntTy},dep_graph::{WorkProductId,WorkProduct},mir::{Statement,StatementKind,Terminator,TerminatorKind,Rvalue,BinOp,Operand,ConstantKind,AggregateKind,interpret::ConstValue,mono::MonoItem}};
1414
use rustc_metadata::EncodedMetadata;
1515
use rustc_span::ErrorGuaranteed;
1616
use std::hash::BuildHasherDefault;
1717
use rustc_session::{config::OutputFilenames,Session};
1818
use rustc_data_structures::fx::FxIndexMap;
19-
#[derive(Debug)]
20-
enum CLROp{
19+
#[derive(Debug,Clone)]
20+
enum BaseIR{
21+
LDConstI32(i32),
2122
STArg(u32),
2223
LDArg(u32),
2324
STLoc(u32),
2425
LDLoc(u32),
26+
Add,
27+
Mul,
28+
Shl,
29+
Return,
2530
}
2631
struct MyBackend;
2732
struct CustomCodegen{}
2833
#[derive(Debug)]
2934
struct CLRMethod{
30-
ops:Vec<CLROp>,
35+
ops:Vec<BaseIR>,
3136
argc:u32,
3237
}
38+
enum LocalPlacement{
39+
Arg(u32),
40+
Var(u32),
41+
}
3342
impl CLRMethod{
3443
fn argc(&self)->u32{self.argc}
44+
fn remove_sl(&mut self)->usize{
45+
let mut opt_ops:Vec<BaseIR> = Vec::with_capacity(self.ops.len());
46+
let mut ops_peek = self.ops.iter().peekable();
47+
while let Some(op) = ops_peek.next(){
48+
match op{
49+
BaseIR::STLoc(local_id)=>{
50+
if let Some(BaseIR::LDLoc(other_id)) = ops_peek.peek(){
51+
//Ops store and the load the same value, being effectively a NOP.
52+
if local_id == other_id{
53+
ops_peek.next();
54+
continue;
55+
}
56+
}
57+
}
58+
_=>(),
59+
}
60+
opt_ops.push(op.clone());
61+
}
62+
self.ops = opt_ops;
63+
self.ops.len()
64+
}
65+
fn opt(&mut self){
66+
const MAX_OPT_PASS:usize = 8;
67+
for _ in 0..MAX_OPT_PASS{
68+
let prev_length = self.ops.len();
69+
if !(self.remove_sl() < prev_length){continue;}
70+
}
71+
}
72+
fn has_return(&self)->bool{true}
3573
fn new(argc:u32)->Self{
3674
Self{argc,ops:Vec::with_capacity(0xF)}
3775
}
38-
fn load(&mut self,var:u32){
39-
if var < self.argc(){
40-
self.ops.push(CLROp::LDArg(var));
76+
fn var_live(&mut self,local:u32){
77+
//TODO: use variable lifetimes!
78+
}
79+
fn var_dead(&mut self,local:u32){
80+
//TODO: use variable lifetimes!
81+
}
82+
fn local_id_placement(&self,local:u32)->LocalPlacement{
83+
// I assume local 0 is supposed to be the return value. TODO: check if this is always the case.
84+
if self.has_return(){
85+
if local == 0{
86+
LocalPlacement::Var(0)
87+
}
88+
else if local - 1 < self.argc(){
89+
LocalPlacement::Arg(local - 1)
90+
}
91+
else{
92+
LocalPlacement::Var(local - self.argc())
93+
}
4194
}
4295
else{
43-
println!("argc:{}, var:{var}",self.argc);
44-
self.ops.push(CLROp::LDLoc(var - self.argc()));
96+
panic!("Can't handle void functions yet. Diagnose MIR to determine what happens to the return var(0)!");
4597
}
98+
99+
}
100+
fn load(&mut self,local:u32){
101+
self.ops.push(match self.local_id_placement(local){
102+
LocalPlacement::Arg(arg_id)=>BaseIR::LDArg(arg_id),
103+
LocalPlacement::Var(var_id)=>BaseIR::LDLoc(var_id),
104+
})
105+
}
106+
fn store(&mut self,local:u32){
107+
self.ops.push(match self.local_id_placement(local){
108+
LocalPlacement::Arg(arg_id)=>BaseIR::STArg(arg_id),
109+
LocalPlacement::Var(var_id)=>BaseIR::STLoc(var_id),
110+
})
111+
}
112+
fn process_constant(&mut self, constant:ConstantKind){
113+
self.ops.push(match constant{
114+
ConstantKind::Val(value,r#type)=> match value{
115+
ConstValue::Scalar(scalar)=>{
116+
match r#type.kind(){
117+
TyKind::Int(IntTy::I32)=>BaseIR::LDConstI32(scalar.to_i32().expect("Type is i32, but odes not fit in i32.")),
118+
_=>todo!("Unhandled type kind {:?}",r#type.kind()),
119+
}
120+
}
121+
_=>todo!("Unhanled constant value {value:?}"),
122+
}
123+
_=>todo!("Unhanled constant {constant:?}"),
124+
});
46125
}
47126
// Makes so the top of the stack is the value of RValue
48127
fn process_operand(&mut self, operand:&Operand){
49128
match operand{
50129
Operand::Copy(place) => self.load(place.local.into()),
130+
//TODO:Do moves need to be treated any diffrently forom copies in the context of CLR?
131+
Operand::Move(place) => self.load(place.local.into()),
132+
Operand::Constant(const_val)=>{
133+
self.process_constant(const_val.literal);
134+
},
51135
_=>todo!("Unhanled operand {operand:?}"),
52136
}
53137
}
54138
// Makes so the top of the stack is the value of RValue
55139
fn process_rvalue(&mut self,rvalue:&Rvalue){
56140
match rvalue{
57141
Rvalue::Use(operand)=>self.process_operand(operand),
142+
Rvalue::BinaryOp(binop,operands)=>{
143+
let (a,b):(_,_) = (&operands.0,&operands.1);
144+
self.process_operand(a);
145+
self.process_operand(b);
146+
self.ops.push(match binop{
147+
BinOp::Add=>BaseIR::Add,
148+
BinOp::Mul=>BaseIR::Mul,
149+
BinOp::Shl=>BaseIR::Shl,
150+
_=>todo!("Unknown binop:{binop:?}"),
151+
});
152+
}
153+
Rvalue::Aggregate(kind,operands)=>{
154+
match kind.as_ref(){
155+
AggregateKind::Adt(def_id,variant_idx,subst_ref,utai,fidx)=>{
156+
//let (def_id,variant_idx,subst_ref,utai,fidx) = *adt;
157+
panic!("def_id:{def_id:?},variant_idx:{variant_idx:?},subst_ref:{subst_ref:?},utai:{utai:?},fidx:{fidx:?},\noperands:{operands}");
158+
}
159+
_=> todo!("Can't yet handle the aggregate of kind {kind:?} and operands:{operands:?}"),
160+
}
161+
}
58162
_=>todo!("Can't yet handle a rvalue of type {rvalue:?}"),
59163
}
60164
}
61-
fn store(&mut self,var:u32){
62-
if var < self.argc(){
63-
self.ops.push(CLROp::STArg(var));
64-
}
65-
else{
66-
self.ops.push(CLROp::STLoc(var - self.argc()));
67-
}
68-
}
69165
fn add_statement(&mut self,statement:&Statement){
166+
println!("statement:{statement:?}");
70167
match &statement.kind{
71168
StatementKind::Assign(asign_box)=>{
72169
let (place,rvalue) = (asign_box.0,&asign_box.1);
73170
self.process_rvalue(rvalue);
74171
self.store(place.local.into());
75172
//panic!("place:{place:?},rvalue:{rvalue:?}");
173+
},
174+
StatementKind::StorageLive(local)=>{
175+
self.var_live((*local).into());
176+
}
177+
StatementKind::StorageDead(local)=>{
178+
self.var_dead((*local).into());
76179
}
77180
_=>todo!("Unhanded statement:{:?}",statement.kind),
78181
}
79182
}
183+
fn add_terminator(&mut self,terminator:&Terminator){
184+
match terminator.kind{
185+
TerminatorKind::Return=>{
186+
if self.has_return(){
187+
self.load(0);
188+
self.ops.push(BaseIR::Return);
189+
}
190+
else{
191+
todo!("Can't yet return from a void method!");
192+
}
193+
}
194+
_=>todo!("Unknown terminator type {terminator:?}"),
195+
}
196+
}
80197
}
81198
impl CustomCodegen{
82199
fn add_fn<'tcx>(&mut self,instance:Instance<'tcx>,tcx: TyCtxt<'tcx>){
@@ -92,8 +209,12 @@ impl CustomCodegen{
92209
for statement in &block_data.statements{
93210
clr_method.add_statement(statement);
94211
}
95-
212+
match &block_data.terminator{
213+
Some(term)=>clr_method.add_terminator(term),
214+
None=>(),
215+
}
96216
}
217+
clr_method.opt();
97218
println!("clr_method:{clr_method:?}");
98219
println!("instance:{instance:?}\n");
99220
}

test/identity.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
pub extern fn identity(a:i32)->i32{a}
2-
/*
3-
pub struct Vector3(f32,f32,f32);
2+
pub extern fn add(a:i32)->i32{a+a}
3+
pub extern fn add2(a:i32,b:i32)->i32{a + b}
4+
pub extern fn sqr_mag(ax:i32,ay:i32)->i32{ax*ax + ay*ay}
5+
pub extern fn pow2(power:i32)->i32{1<<power}
6+
struct Vector3{x:f32,y:f32,z:f32}
7+
48
impl std::ops::Add for Vector3{
5-
type Output = Self;
9+
type Output = Vector3;
610
fn add(self,rhs:Self)->Self{
7-
Self(self.0 + rhs.0, self.1 + rhs.1, self.2 + rhs.2)
11+
Self{x:self.x + rhs.x,y:self.y + rhs.y,z:self.z + rhs.z}
812
}
9-
}*/
13+
}

0 commit comments

Comments
 (0)