Skip to content

Commit 02017b3

Browse files
committed
New trans codepath that builds fn body from MIR instead.
1 parent 877b93a commit 02017b3

File tree

10 files changed

+887
-0
lines changed

10 files changed

+887
-0
lines changed

src/librustc_trans/trans/common.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,12 @@ pub fn C_floating(s: &str, t: Type) -> ValueRef {
743743
}
744744
}
745745

746+
pub fn C_floating_f64(f: f64, t: Type) -> ValueRef {
747+
unsafe {
748+
llvm::LLVMConstReal(t.to_ref(), f)
749+
}
750+
}
751+
746752
pub fn C_nil(ccx: &CrateContext) -> ValueRef {
747753
C_struct(ccx, &[], false)
748754
}

src/librustc_trans/trans/mir/block.rs

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use llvm::BasicBlockRef;
12+
use rustc_mir::repr as mir;
13+
use trans::base;
14+
use trans::build;
15+
use trans::common::Block;
16+
use trans::debuginfo::DebugLoc;
17+
18+
use super::MirContext;
19+
20+
impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
21+
pub fn trans_block(&mut self, bb: mir::BasicBlock) {
22+
debug!("trans_block({:?})", bb);
23+
24+
let mut bcx = self.bcx(bb);
25+
let data = self.mir.basic_block_data(bb);
26+
27+
for statement in &data.statements {
28+
bcx = self.trans_statement(bcx, statement);
29+
}
30+
31+
debug!("trans_block: terminator: {:?}", data.terminator);
32+
33+
match data.terminator {
34+
mir::Terminator::Goto { target } => {
35+
build::Br(bcx, self.llblock(target), DebugLoc::None)
36+
}
37+
38+
mir::Terminator::Panic { .. } => {
39+
unimplemented!()
40+
}
41+
42+
mir::Terminator::If { ref cond, targets: [true_bb, false_bb] } => {
43+
let cond = self.trans_operand(bcx, cond);
44+
let lltrue = self.llblock(true_bb);
45+
let llfalse = self.llblock(false_bb);
46+
build::CondBr(bcx, cond.llval, lltrue, llfalse, DebugLoc::None);
47+
}
48+
49+
mir::Terminator::Switch { .. } => {
50+
unimplemented!()
51+
}
52+
53+
mir::Terminator::Diverge => {
54+
if let Some(llpersonalityslot) = self.llpersonalityslot {
55+
let lp = build::Load(bcx, llpersonalityslot);
56+
// FIXME(lifetime) base::call_lifetime_end(bcx, self.personality);
57+
build::Resume(bcx, lp);
58+
} else {
59+
// This fn never encountered anything fallible, so
60+
// a Diverge cannot actually happen. Note that we
61+
// do a total hack to ensure that we visit the
62+
// DIVERGE block last.
63+
build::Unreachable(bcx);
64+
}
65+
}
66+
67+
mir::Terminator::Return => {
68+
let return_ty = bcx.monomorphize(&self.mir.return_ty);
69+
base::build_return_block(bcx.fcx, bcx, return_ty, DebugLoc::None);
70+
}
71+
72+
mir::Terminator::Call { .. } => {
73+
unimplemented!()
74+
//let llbb = unimplemented!(); // self.make_landing_pad(panic_bb);
75+
//
76+
//let tr_dest = self.trans_lvalue(bcx, &data.destination);
77+
//
78+
//// Create the callee. This will always be a fn
79+
//// ptr and hence a kind of scalar.
80+
//let callee = self.trans_operand(bcx, &data.func);
81+
//
82+
//// Process the arguments.
83+
//
84+
//let args = unimplemented!();
85+
//
86+
//callee::trans_call_inner(bcx,
87+
// DebugLoc::None,
88+
// |bcx, _| Callee {
89+
// bcx: bcx,
90+
// data: CalleeData::Fn(callee.llval),
91+
// ty: callee.ty,
92+
// },
93+
// args,
94+
// Some(Dest::SaveIn(tr_dest.llval)));
95+
}
96+
}
97+
}
98+
99+
fn bcx(&self, bb: mir::BasicBlock) -> Block<'bcx, 'tcx> {
100+
self.blocks[bb.index()]
101+
}
102+
103+
fn llblock(&self, bb: mir::BasicBlock) -> BasicBlockRef {
104+
self.blocks[bb.index()].llbb
105+
}
106+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use llvm::ValueRef;
12+
use rustc::middle::const_eval::ConstVal;
13+
use rustc_mir::repr as mir;
14+
use trans::consts::{self, TrueConst};
15+
use trans::common::{self, Block};
16+
use trans::type_of;
17+
18+
use super::MirContext;
19+
20+
impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
21+
pub fn trans_constant(&mut self,
22+
bcx: Block<'bcx, 'tcx>,
23+
constant: &mir::Constant<'tcx>)
24+
-> ValueRef
25+
{
26+
let ccx = bcx.ccx();
27+
let constant_ty = bcx.monomorphize(&constant.ty);
28+
let llty = type_of::type_of(ccx, constant_ty);
29+
match constant.literal {
30+
mir::Literal::Item { .. } => {
31+
unimplemented!()
32+
}
33+
mir::Literal::Value { ref value } => {
34+
match *value {
35+
ConstVal::Float(v) => common::C_floating_f64(v, llty),
36+
ConstVal::Bool(v) => common::C_bool(ccx, v),
37+
ConstVal::Int(v) => common::C_integral(llty, v as u64, true),
38+
ConstVal::Uint(v) => common::C_integral(llty, v, false),
39+
ConstVal::Str(ref v) => common::C_str_slice(ccx, v.clone()),
40+
ConstVal::ByteStr(ref v) => consts::addr_of(ccx,
41+
common::C_bytes(ccx, v),
42+
1,
43+
"byte_str"),
44+
ConstVal::Struct(id) | ConstVal::Tuple(id) => {
45+
let expr = bcx.tcx().map.expect_expr(id);
46+
let (llval, _) = match consts::const_expr(ccx,
47+
expr,
48+
bcx.fcx.param_substs,
49+
None,
50+
TrueConst::Yes) {
51+
Ok(v) => v,
52+
Err(_) => panic!("constant eval failure"),
53+
};
54+
llval
55+
}
56+
ConstVal::Function(_) => {
57+
unimplemented!()
58+
}
59+
}
60+
}
61+
}
62+
}
63+
}
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use llvm::ValueRef;
12+
use rustc::middle::ty::Ty;
13+
use rustc_mir::repr as mir;
14+
use rustc_mir::tcx::LvalueTy;
15+
use trans::adt;
16+
use trans::base;
17+
use trans::build;
18+
use trans::common::{self, Block};
19+
use trans::debuginfo::DebugLoc;
20+
use trans::machine;
21+
use trans::tvec;
22+
23+
use super::MirContext;
24+
25+
#[derive(Copy, Clone)]
26+
pub struct LvalueRef<'tcx> {
27+
/// Pointer to the contents of the lvalue
28+
pub llval: ValueRef,
29+
30+
/// Monomorphized type of this lvalue, including variant information
31+
pub ty: LvalueTy<'tcx>,
32+
}
33+
34+
impl<'tcx> LvalueRef<'tcx> {
35+
pub fn new(llval: ValueRef, lvalue_ty: LvalueTy<'tcx>) -> LvalueRef<'tcx> {
36+
LvalueRef { llval: llval, ty: lvalue_ty }
37+
}
38+
39+
pub fn alloca<'bcx>(bcx: Block<'bcx, 'tcx>,
40+
ty: Ty<'tcx>,
41+
name: &str)
42+
-> LvalueRef<'tcx>
43+
{
44+
let lltemp = base::alloc_ty(bcx, ty, name);
45+
LvalueRef::new(lltemp, LvalueTy::from_ty(ty))
46+
}
47+
}
48+
49+
impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
50+
pub fn trans_lvalue(&mut self,
51+
bcx: Block<'bcx, 'tcx>,
52+
lvalue: &mir::Lvalue<'tcx>)
53+
-> LvalueRef<'tcx> {
54+
debug!("trans_lvalue(lvalue={:?})", lvalue);
55+
56+
let fcx = bcx.fcx;
57+
let ccx = fcx.ccx;
58+
let tcx = bcx.tcx();
59+
match *lvalue {
60+
mir::Lvalue::Var(index) => self.vars[index as usize],
61+
mir::Lvalue::Temp(index) => self.temps[index as usize],
62+
mir::Lvalue::Arg(index) => self.args[index as usize],
63+
mir::Lvalue::Static(_def_id) => unimplemented!(),
64+
mir::Lvalue::ReturnPointer => {
65+
let return_ty = bcx.monomorphize(&self.mir.return_ty);
66+
let llval = fcx.get_ret_slot(bcx, return_ty, "return");
67+
LvalueRef::new(llval, LvalueTy::from_ty(return_ty.unwrap()))
68+
}
69+
mir::Lvalue::Projection(ref projection) => {
70+
let tr_base = self.trans_lvalue(bcx, &projection.base);
71+
let projected_ty = tr_base.ty.projection_ty(tcx, &projection.elem);
72+
let llprojected = match projection.elem {
73+
mir::ProjectionElem::Deref => {
74+
let base_ty = tr_base.ty.to_ty(tcx);
75+
base::load_ty(bcx, tr_base.llval, base_ty)
76+
}
77+
mir::ProjectionElem::Field(ref field) => {
78+
let base_ty = tr_base.ty.to_ty(tcx);
79+
let base_repr = adt::represent_type(ccx, base_ty);
80+
let discr = match tr_base.ty {
81+
LvalueTy::Ty { .. } => 0,
82+
LvalueTy::Downcast { adt_def: _, substs: _, variant_index: v } => v,
83+
};
84+
let discr = discr as u64;
85+
adt::trans_field_ptr(bcx, &base_repr, tr_base.llval, discr, field.index())
86+
}
87+
mir::ProjectionElem::Index(ref index) => {
88+
let base_ty = tr_base.ty.to_ty(tcx);
89+
let index = self.trans_operand(bcx, index);
90+
let llindex = self.prepare_index(bcx, index.llval);
91+
let (llbase, _) = tvec::get_base_and_len(bcx, tr_base.llval, base_ty);
92+
build::InBoundsGEP(bcx, llbase, &[llindex])
93+
}
94+
mir::ProjectionElem::ConstantIndex { offset,
95+
from_end: false,
96+
min_length: _ } => {
97+
let base_ty = tr_base.ty.to_ty(tcx);
98+
let lloffset = common::C_u32(bcx.ccx(), offset);
99+
let llindex = self.prepare_index(bcx, lloffset);
100+
let (llbase, _) = tvec::get_base_and_len(bcx,
101+
tr_base.llval,
102+
base_ty);
103+
build::InBoundsGEP(bcx, llbase, &[llindex])
104+
}
105+
mir::ProjectionElem::ConstantIndex { offset,
106+
from_end: true,
107+
min_length: _ } => {
108+
let lloffset = common::C_u32(bcx.ccx(), offset);
109+
let base_ty = tr_base.ty.to_ty(tcx);
110+
let (llbase, lllen) = tvec::get_base_and_len(bcx,
111+
tr_base.llval,
112+
base_ty);
113+
let llindex = build::Sub(bcx, lllen, lloffset, DebugLoc::None);
114+
let llindex = self.prepare_index(bcx, llindex);
115+
build::InBoundsGEP(bcx, llbase, &[llindex])
116+
}
117+
mir::ProjectionElem::Downcast(..) => {
118+
tr_base.llval
119+
}
120+
};
121+
LvalueRef {
122+
llval: llprojected,
123+
ty: projected_ty,
124+
}
125+
}
126+
}
127+
}
128+
129+
/// Adjust the bitwidth of an index since LLVM is less forgiving
130+
/// than we are.
131+
///
132+
/// nmatsakis: is this still necessary? Not sure.
133+
fn prepare_index(&mut self,
134+
bcx: Block<'bcx, 'tcx>,
135+
llindex: ValueRef)
136+
-> ValueRef
137+
{
138+
let ccx = bcx.ccx();
139+
let index_size = machine::llbitsize_of_real(bcx.ccx(), common::val_ty(llindex));
140+
let int_size = machine::llbitsize_of_real(bcx.ccx(), ccx.int_type());
141+
if index_size < int_size {
142+
build::ZExt(bcx, llindex, ccx.int_type())
143+
} else if index_size > int_size {
144+
build::Trunc(bcx, llindex, ccx.int_type())
145+
} else {
146+
llindex
147+
}
148+
}
149+
}

0 commit comments

Comments
 (0)