Skip to content

Commit ece05d3

Browse files
committed
Implement references to functions and constants
1 parent 5fb2edc commit ece05d3

File tree

13 files changed

+394
-16
lines changed

13 files changed

+394
-16
lines changed

src/librustc/mir/repr.rs

+10
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

+1
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

+17-5
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

+1
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

+5-1
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

+2-1
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

+1-1
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

+6-8
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

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

src/librustc_trans/trans/mir/mod.rs

+1
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

+10
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> {
+28
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)