Skip to content

Commit 379cef8

Browse files
committed
Clean-up casts
typeck part works, trans part is broken (I get LLVM broken function assertions, my trans-fu is bad).
1 parent aecf3d8 commit 379cef8

23 files changed

+842
-354
lines changed

src/librustc/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ pub mod back {
9292
pub mod middle {
9393
pub mod astconv_util;
9494
pub mod astencode;
95+
pub mod cast;
9596
pub mod cfg;
9697
pub mod check_const;
9798
pub mod check_static_recursion;

src/librustc/middle/cast.rs

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
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+
// Helpers for handling cast expressions, used in both
12+
// typeck and trans.
13+
14+
use middle::ty::{self, Ty};
15+
16+
use syntax::ast;
17+
18+
19+
#[derive(Copy, Clone, PartialEq, Eq)]
20+
pub enum IntTy {
21+
U(ast::UintTy),
22+
I,
23+
CEnum,
24+
Bool,
25+
Char
26+
}
27+
28+
// Valid types for the result of a non-coercion cast
29+
#[derive(Copy, Clone, PartialEq, Eq)]
30+
pub enum CastTy<'tcx> {
31+
Int(IntTy),
32+
Float,
33+
FPtr,
34+
Ptr(&'tcx ty::mt<'tcx>),
35+
RPtr(&'tcx ty::mt<'tcx>),
36+
}
37+
38+
impl<'tcx> CastTy<'tcx> {
39+
pub fn recognize(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>)
40+
-> Option<CastTy<'tcx>> {
41+
match t.sty {
42+
ty::ty_bool => Some(CastTy::Int(IntTy::Bool)),
43+
ty::ty_char => Some(CastTy::Int(IntTy::Char)),
44+
ty::ty_int(_) => Some(CastTy::Int(IntTy::I)),
45+
ty::ty_uint(u) => Some(CastTy::Int(IntTy::U(u))),
46+
ty::ty_float(_) => Some(CastTy::Float),
47+
ty::ty_enum(..) if ty::type_is_c_like_enum(
48+
tcx, t) => Some(CastTy::Int(IntTy::CEnum)),
49+
ty::ty_ptr(ref mt) => Some(CastTy::Ptr(mt)),
50+
ty::ty_rptr(_, ref mt) => Some(CastTy::RPtr(mt)),
51+
ty::ty_bare_fn(..) => Some(CastTy::FPtr),
52+
_ => None,
53+
}
54+
}
55+
}

src/librustc/middle/const_eval.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -992,7 +992,7 @@ fn cast_const<'tcx>(tcx: &ty::ctxt<'tcx>, val: const_val, ty: Ty) -> CastResult
992992
macro_rules! convert_val {
993993
($intermediate_ty:ty, $const_type:ident, $target_ty:ty) => {
994994
match val {
995-
const_bool(b) => Ok($const_type(b as $intermediate_ty as $target_ty)),
995+
const_bool(b) => Ok($const_type(b as u64 as $intermediate_ty as $target_ty)),
996996
const_uint(u) => Ok($const_type(u as $intermediate_ty as $target_ty)),
997997
const_int(i) => Ok($const_type(i as $intermediate_ty as $target_ty)),
998998
const_float(f) => Ok($const_type(f as $intermediate_ty as $target_ty)),

src/librustc/middle/ty.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -288,15 +288,6 @@ pub struct field_ty {
288288
pub origin: ast::DefId, // The DefId of the struct in which the field is declared.
289289
}
290290

291-
// Contains information needed to resolve types and (in the future) look up
292-
// the types of AST nodes.
293-
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
294-
pub struct creader_cache_key {
295-
pub cnum: CrateNum,
296-
pub pos: usize,
297-
pub len: usize
298-
}
299-
300291
#[derive(Clone, PartialEq, RustcDecodable, RustcEncodable)]
301292
pub struct ItemVariances {
302293
pub types: VecPerParamSpace<Variance>,
@@ -556,6 +547,15 @@ pub enum vtable_origin<'tcx> {
556547
// expr to the associated trait ref.
557548
pub type ObjectCastMap<'tcx> = RefCell<NodeMap<ty::PolyTraitRef<'tcx>>>;
558549

550+
// Contains information needed to resolve types and (in the future) look up
551+
// the types of AST nodes.
552+
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
553+
pub struct creader_cache_key {
554+
pub cnum: CrateNum,
555+
pub pos: usize,
556+
pub len: usize
557+
}
558+
559559
/// A restriction that certain types must be the same size. The use of
560560
/// `transmute` gives rise to these restrictions. These generally
561561
/// cannot be checked until trans; therefore, each call to `transmute`

src/librustc_trans/trans/consts.rs

+39-30
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use trans::declare;
2929
use trans::monomorphize;
3030
use trans::type_::Type;
3131
use trans::type_of;
32+
use middle::cast::{CastTy,IntTy};
3233
use middle::subst::Substs;
3334
use middle::ty::{self, Ty};
3435
use util::ppaux::{Repr, ty_to_string};
@@ -616,53 +617,61 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
616617
}
617618
}
618619
ast::ExprCast(ref base, _) => {
619-
let llty = type_of::type_of(cx, ety);
620-
let (v, basety) = const_expr(cx, &**base, param_substs);
621-
if expr::cast_is_noop(basety, ety) {
620+
let t_1 = ety;
621+
let llty = type_of::type_of(cx, t_1);
622+
let (v, t_e) = const_expr(cx, &**base, param_substs);
623+
if expr::cast_is_noop(t_e, t_1) {
622624
return v;
623625
}
624-
match (expr::cast_type_kind(cx.tcx(), basety),
625-
expr::cast_type_kind(cx.tcx(), ety)) {
626-
627-
(expr::cast_integral, expr::cast_integral) => {
628-
let s = ty::type_is_signed(basety) as Bool;
626+
if type_is_fat_ptr(cx.tcx(), t_e) {
627+
// Fat pointer casts.
628+
let t_1_inner = ty::deref(t_1, true).expect("cast to non-pointer").ty;
629+
let ptr_ty = type_of::in_memory_type_of(cx, t_1_inner).ptr_to();
630+
let addr = ptrcast(const_get_elt(cx, v, &[abi::FAT_PTR_ADDR as u32]),
631+
ptr_ty);
632+
if type_is_fat_ptr(cx.tcx(), t_1) {
633+
let info = const_get_elt(cx, v, &[abi::FAT_PTR_EXTRA as u32]);
634+
return C_struct(cx, &[addr, info], false)
635+
} else {
636+
return addr;
637+
}
638+
}
639+
match (CastTy::recognize(cx.tcx(), t_e).expect("bad input type for cast"),
640+
CastTy::recognize(cx.tcx(), t_1).expect("bad output type for cast")) {
641+
(CastTy::Int(IntTy::CEnum), CastTy::Int(_)) => {
642+
let repr = adt::represent_type(cx, t_e);
643+
let discr = adt::const_get_discrim(cx, &*repr, v);
644+
let iv = C_integral(cx.int_type(), discr, false);
645+
let s = ty::type_is_signed(t_1) as Bool;
646+
llvm::LLVMConstIntCast(iv, llty.to_ref(), s)
647+
}
648+
(CastTy::Int(_), CastTy::Int(_)) => {
649+
let s = ty::type_is_signed(t_1) as Bool;
629650
llvm::LLVMConstIntCast(v, llty.to_ref(), s)
630651
}
631-
(expr::cast_integral, expr::cast_float) => {
632-
if ty::type_is_signed(basety) {
652+
(CastTy::Int(_), CastTy::Float) => {
653+
if ty::type_is_signed(t_1) {
633654
llvm::LLVMConstSIToFP(v, llty.to_ref())
634655
} else {
635656
llvm::LLVMConstUIToFP(v, llty.to_ref())
636657
}
637658
}
638-
(expr::cast_float, expr::cast_float) => {
659+
(CastTy::Float, CastTy::Float) => {
639660
llvm::LLVMConstFPCast(v, llty.to_ref())
640661
}
641-
(expr::cast_float, expr::cast_integral) => {
642-
if ty::type_is_signed(ety) { llvm::LLVMConstFPToSI(v, llty.to_ref()) }
662+
(CastTy::Float, CastTy::Int(_)) => {
663+
if ty::type_is_signed(t_1) { llvm::LLVMConstFPToSI(v, llty.to_ref()) }
643664
else { llvm::LLVMConstFPToUI(v, llty.to_ref()) }
644665
}
645-
(expr::cast_enum, expr::cast_integral) => {
646-
let repr = adt::represent_type(cx, basety);
647-
let discr = adt::const_get_discrim(cx, &*repr, v);
648-
let iv = C_integral(cx.int_type(), discr, false);
649-
let ety_cast = expr::cast_type_kind(cx.tcx(), ety);
650-
match ety_cast {
651-
expr::cast_integral => {
652-
let s = ty::type_is_signed(ety) as Bool;
653-
llvm::LLVMConstIntCast(iv, llty.to_ref(), s)
654-
}
655-
_ => cx.sess().bug("enum cast destination is not \
656-
integral")
657-
}
658-
}
659-
(expr::cast_pointer, expr::cast_pointer) => {
666+
(CastTy::Ptr(_), CastTy::Ptr(_)) | (CastTy::FPtr, CastTy::Ptr(_))
667+
| (CastTy::RPtr(_), CastTy::Ptr(_)) => {
660668
ptrcast(v, llty)
661669
}
662-
(expr::cast_integral, expr::cast_pointer) => {
670+
(CastTy::FPtr, CastTy::FPtr) => ptrcast(v, llty), // isn't this a coercion?
671+
(CastTy::Int(_), CastTy::Ptr(_)) => {
663672
llvm::LLVMConstIntToPtr(v, llty.to_ref())
664673
}
665-
(expr::cast_pointer, expr::cast_integral) => {
674+
(CastTy::Ptr(_), CastTy::Int(_)) | (CastTy::FPtr, CastTy::Int(_)) => {
666675
llvm::LLVMConstPtrToInt(v, llty.to_ref())
667676
}
668677
_ => {

0 commit comments

Comments
 (0)