Skip to content

Commit a5e7a61

Browse files
committed
Implement references to functions and constants
1 parent 59e6b20 commit a5e7a61

File tree

13 files changed

+395
-16
lines changed

13 files changed

+395
-16
lines changed

src/librustc/mir/repr.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,10 +698,20 @@ pub struct Constant<'tcx> {
698698
pub literal: Literal<'tcx>,
699699
}
700700

701+
#[derive(Clone, Copy, Debug, PartialEq, RustcEncodable, RustcDecodable)]
702+
pub enum ItemKind {
703+
Constant,
704+
Function,
705+
Struct,
706+
Variant,
707+
Method,
708+
}
709+
701710
#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
702711
pub enum Literal<'tcx> {
703712
Item {
704713
def_id: DefId,
714+
kind: ItemKind,
705715
substs: &'tcx Substs<'tcx>,
706716
},
707717
Value {

src/librustc_mir/build/misc.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
6666
-> Operand<'tcx> {
6767
let literal = Literal::Item {
6868
def_id: item_ref.def_id,
69+
kind: item_ref.kind,
6970
substs: item_ref.substs,
7071
};
7172
self.literal_operand(span, item_ref.ty, literal)

src/librustc_mir/hair/cx/expr.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,7 @@ fn method_callee<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
480480
kind: ExprKind::Literal {
481481
literal: Literal::Item {
482482
def_id: callee.def_id,
483+
kind: ItemKind::Method,
483484
substs: callee.substs,
484485
},
485486
},
@@ -520,18 +521,29 @@ fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr)
520521
def::DefVariant(_, def_id, false) |
521522
def::DefStruct(def_id) |
522523
def::DefFn(def_id, _) |
523-
def::DefMethod(def_id) =>
524+
def::DefMethod(def_id) => {
525+
let kind = match def {
526+
def::DefVariant(..) => ItemKind::Variant,
527+
def::DefStruct(..) => ItemKind::Struct,
528+
def::DefFn(..) => ItemKind::Function,
529+
def::DefMethod(..) => ItemKind::Method,
530+
_ => panic!()
531+
};
524532
ExprKind::Literal {
525-
literal: Literal::Item { def_id: def_id, substs: substs }
526-
},
527-
533+
literal: Literal::Item { def_id: def_id, kind: kind, substs: substs }
534+
}
535+
},
528536
def::DefConst(def_id) |
529537
def::DefAssociatedConst(def_id) => {
530538
if let Some(v) = cx.try_const_eval_literal(expr) {
531539
ExprKind::Literal { literal: v }
532540
} else {
533541
ExprKind::Literal {
534-
literal: Literal::Item { def_id: def_id, substs: substs }
542+
literal: Literal::Item {
543+
def_id: def_id,
544+
kind: ItemKind::Constant,
545+
substs: substs
546+
}
535547
}
536548
}
537549
}

src/librustc_mir/hair/cx/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ impl<'a,'tcx:'a> Cx<'a, 'tcx> {
139139
let method_ty = method_ty.ty.subst(self.tcx, &substs);
140140
return ItemRef {
141141
ty: method_ty,
142+
kind: ItemKind::Method,
142143
def_id: method.def_id,
143144
substs: self.tcx.mk_substs(substs),
144145
};

src/librustc_mir/hair/cx/pattern.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,11 @@ impl<'patcx, 'cx, 'tcx> PatCx<'patcx, 'cx, 'tcx> {
9797
Literal::Value { value: value }
9898
} else {
9999
let substs = self.cx.tcx.mk_substs(Substs::empty());
100-
Literal::Item { def_id: def_id, substs: substs }
100+
Literal::Item {
101+
def_id: def_id,
102+
kind: ItemKind::Constant,
103+
substs: substs
104+
}
101105
};
102106
PatternKind::Constant { value: literal }
103107
}

src/librustc_mir/hair/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
//! unit-tested and separated from the Rust source and compiler data
1515
//! structures.
1616
17-
use rustc::mir::repr::{BinOp, BorrowKind, Field, Literal, Mutability, UnOp};
17+
use rustc::mir::repr::{BinOp, BorrowKind, Field, Literal, Mutability, UnOp, ItemKind};
1818
use rustc::middle::def_id::DefId;
1919
use rustc::middle::region::CodeExtent;
2020
use rustc::middle::subst::Substs;
@@ -29,6 +29,7 @@ pub mod cx;
2929
#[derive(Clone, Debug)]
3030
pub struct ItemRef<'tcx> {
3131
pub ty: Ty<'tcx>,
32+
pub kind: ItemKind,
3233
pub def_id: DefId,
3334
pub substs: &'tcx Substs<'tcx>,
3435
}

src/librustc_trans/trans/meth.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ fn trans_trait_callee_from_llval<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
473473
///
474474
/// In fact, all virtual calls can be thought of as normal trait calls
475475
/// that go through this shim function.
476-
fn trans_object_shim<'a, 'tcx>(
476+
pub fn trans_object_shim<'a, 'tcx>(
477477
ccx: &'a CrateContext<'a, 'tcx>,
478478
upcast_trait_ref: ty::PolyTraitRef<'tcx>,
479479
method_id: DefId,

src/librustc_trans/trans/mir/constant.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ use rustc::mir::repr as mir;
1414
use trans::consts;
1515
use trans::common::{self, Block};
1616

17-
use super::operand::OperandRef;
17+
18+
use super::operand::{OperandRef, OperandValue};
1819
use super::MirContext;
1920

2021
impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
@@ -24,8 +25,6 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
2425
ty: Ty<'tcx>)
2526
-> OperandRef<'tcx>
2627
{
27-
use super::operand::OperandValue::{Ref, Immediate};
28-
2928
let ccx = bcx.ccx();
3029
let val = consts::trans_constval(ccx, cv, ty, bcx.fcx.param_substs);
3130
let val = if common::type_is_immediate(ccx, ty) {
@@ -47,13 +46,12 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
4746
constant: &mir::Constant<'tcx>)
4847
-> OperandRef<'tcx>
4948
{
50-
let constant_ty = bcx.monomorphize(&constant.ty);
49+
let ty = bcx.monomorphize(&constant.ty);
5150
match constant.literal {
52-
mir::Literal::Item { .. } => {
53-
unimplemented!()
54-
}
51+
mir::Literal::Item { def_id, kind, substs } =>
52+
self.trans_item_ref(bcx, ty, kind, substs, def_id),
5553
mir::Literal::Value { ref value } => {
56-
self.trans_constval(bcx, value, constant_ty)
54+
self.trans_constval(bcx, value, ty)
5755
}
5856
}
5957
}

src/librustc_trans/trans/mir/did.rs

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
// Copyright 2015 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+
//! Code for translating references to other items (DefIds).
12+
13+
use syntax::codemap::DUMMY_SP;
14+
use rustc::front::map;
15+
use rustc::middle::ty::{self, Ty, HasTypeFlags};
16+
use rustc::middle::subst::Substs;
17+
use rustc::middle::const_eval;
18+
use rustc::middle::def_id::DefId;
19+
use rustc::middle::subst;
20+
use rustc::middle::traits;
21+
use rustc::mir::repr::ItemKind;
22+
use trans::common::{Block, fulfill_obligation};
23+
use trans::base;
24+
use trans::expr;
25+
use trans::monomorphize;
26+
use trans::meth;
27+
use trans::inline;
28+
29+
use super::MirContext;
30+
use super::operand::{OperandRef, OperandValue};
31+
32+
impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
33+
/// Translate reference to item.
34+
pub fn trans_item_ref(&mut self,
35+
bcx: Block<'bcx, 'tcx>,
36+
ty: Ty<'tcx>,
37+
kind: ItemKind,
38+
substs: &'tcx Substs<'tcx>,
39+
did: DefId)
40+
-> OperandRef<'tcx> {
41+
match kind {
42+
ItemKind::Function |
43+
ItemKind::Struct |
44+
ItemKind::Variant => self.trans_fn_ref(bcx, ty, substs, did),
45+
ItemKind::Method => match bcx.tcx().impl_or_trait_item(did).container() {
46+
ty::ImplContainer(_) => self.trans_fn_ref(bcx, ty, substs, did),
47+
ty::TraitContainer(tdid) => self.trans_static_method(bcx, ty, did, tdid, substs)
48+
},
49+
ItemKind::Constant => {
50+
let did = inline::maybe_instantiate_inline(bcx.ccx(), did);
51+
let expr = const_eval::lookup_const_by_id(bcx.tcx(), did, None)
52+
.expect("def was const, but lookup_const_by_id failed");
53+
let d = expr::trans(bcx, expr);
54+
OperandRef::from_rvalue_datum(d.datum.to_rvalue_datum(d.bcx, "").datum)
55+
}
56+
}
57+
}
58+
59+
/// Translates references to a function-like items.
60+
///
61+
/// That includes regular functions, non-static methods, struct and enum variant constructors,
62+
/// closures and possibly more.
63+
///
64+
/// This is an adaptation of callee::trans_fn_ref_with_substs.
65+
pub fn trans_fn_ref(&mut self,
66+
bcx: Block<'bcx, 'tcx>,
67+
ty: Ty<'tcx>,
68+
substs: &'tcx Substs<'tcx>,
69+
did: DefId)
70+
-> OperandRef<'tcx> {
71+
let did = inline::maybe_instantiate_inline(bcx.ccx(), did);
72+
73+
if !substs.types.is_empty() || is_named_tuple_constructor(bcx.tcx(), did) {
74+
let (val, fn_ty, _) = monomorphize::monomorphic_fn(bcx.ccx(), did, substs, None);
75+
// FIXME: cast fnptr to proper type if necessary
76+
OperandRef {
77+
ty: fn_ty,
78+
val: OperandValue::Immediate(val)
79+
}
80+
} else {
81+
let val = if let Some(node_id) = bcx.tcx().map.as_local_node_id(did) {
82+
base::get_item_val(bcx.ccx(), node_id)
83+
} else {
84+
base::trans_external_path(bcx.ccx(), did, ty)
85+
};
86+
// FIXME: cast fnptr to proper type if necessary
87+
OperandRef {
88+
ty: ty,
89+
val: OperandValue::Immediate(val)
90+
}
91+
}
92+
}
93+
94+
/// Translates references to static methods.
95+
///
96+
/// This is an adaptation of meth::trans_static_method_callee
97+
pub fn trans_static_method(&mut self,
98+
bcx: Block<'bcx, 'tcx>,
99+
ty: Ty<'tcx>,
100+
method_id: DefId,
101+
trait_id: DefId,
102+
substs: &'tcx Substs<'tcx>)
103+
-> OperandRef<'tcx> {
104+
let ccx = bcx.ccx();
105+
let tcx = bcx.tcx();
106+
let mname = tcx.item_name(method_id);
107+
let subst::SeparateVecsPerParamSpace {
108+
types: rcvr_type,
109+
selfs: rcvr_self,
110+
fns: rcvr_method
111+
} = substs.clone().types.split();
112+
let trait_substs = Substs::erased(
113+
subst::VecPerParamSpace::new(rcvr_type, rcvr_self, Vec::new())
114+
);
115+
let trait_substs = tcx.mk_substs(trait_substs);
116+
let trait_ref = ty::Binder(ty::TraitRef::new(trait_id, trait_substs));
117+
let vtbl = fulfill_obligation(ccx, DUMMY_SP, trait_ref);
118+
match vtbl {
119+
traits::VtableImpl(traits::VtableImplData { impl_def_id, substs: imp_substs, .. }) => {
120+
assert!(!imp_substs.types.needs_infer());
121+
let subst::SeparateVecsPerParamSpace {
122+
types: impl_type,
123+
selfs: impl_self,
124+
fns: _
125+
} = imp_substs.types.split();
126+
let callee_substs = Substs::erased(
127+
subst::VecPerParamSpace::new(impl_type, impl_self, rcvr_method)
128+
);
129+
let mth = tcx.get_impl_method(impl_def_id, callee_substs, mname);
130+
let mthsubsts = tcx.mk_substs(mth.substs);
131+
self.trans_fn_ref(bcx, ty, mthsubsts, mth.method.def_id)
132+
},
133+
traits::VtableObject(ref data) => {
134+
let idx = traits::get_vtable_index_of_object_method(tcx, data, method_id);
135+
OperandRef::from_rvalue_datum(
136+
meth::trans_object_shim(ccx, data.upcast_trait_ref.clone(), method_id, idx)
137+
)
138+
}
139+
_ => {
140+
tcx.sess.bug(&format!("static call to invalid vtable: {:?}", vtbl));
141+
}
142+
}
143+
}
144+
}
145+
146+
fn is_named_tuple_constructor(tcx: &ty::ctxt, def_id: DefId) -> bool {
147+
let node_id = match tcx.map.as_local_node_id(def_id) {
148+
Some(n) => n,
149+
None => { return false; }
150+
};
151+
match tcx.map.find(node_id).expect("local item should be in ast map") {
152+
map::NodeVariant(v) => {
153+
v.node.data.is_tuple()
154+
}
155+
map::NodeStructCtor(_) => true,
156+
_ => false
157+
}
158+
}

src/librustc_trans/trans/mir/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,3 +192,4 @@ mod lvalue;
192192
mod rvalue;
193193
mod operand;
194194
mod statement;
195+
mod did;

src/librustc_trans/trans/mir/operand.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,16 @@ impl<'tcx> OperandRef<'tcx> {
7676
}
7777
}
7878
}
79+
80+
pub fn from_rvalue_datum(datum: datum::Datum<'tcx, datum::Rvalue>) -> OperandRef {
81+
OperandRef {
82+
ty: datum.ty,
83+
val: match datum.kind.mode {
84+
datum::RvalueMode::ByRef => OperandValue::Ref(datum.val),
85+
datum::RvalueMode::ByValue => OperandValue::Immediate(datum.val),
86+
}
87+
}
88+
}
7989
}
8090

8191
impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2015 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+
12+
pub struct S(pub u8);
13+
14+
impl S {
15+
pub fn hey() -> u8 { 24 }
16+
}
17+
18+
pub trait X {
19+
fn hoy(&self) -> u8 { 25 }
20+
}
21+
22+
impl X for S {}
23+
24+
pub enum E {
25+
U(u8)
26+
}
27+
28+
pub fn regular_fn() -> u8 { 12 }

0 commit comments

Comments
 (0)