Skip to content

Commit

Permalink
rustc_trans: remove the bulk of old trans and most of its support code.
Browse files Browse the repository at this point in the history
  • Loading branch information
eddyb committed Aug 24, 2016
1 parent cb9b0ed commit d0654ae
Show file tree
Hide file tree
Showing 29 changed files with 463 additions and 10,730 deletions.
2,012 changes: 0 additions & 2,012 deletions src/librustc_trans/_match.rs

This file was deleted.

223 changes: 12 additions & 211 deletions src/librustc_trans/adt.rs
Expand Up @@ -53,14 +53,9 @@ use rustc::ty::{self, Ty, TyCtxt};
use syntax::ast;
use syntax::attr;
use syntax::attr::IntType;
use _match;
use abi::FAT_PTR_ADDR;
use base::InitAlloca;
use build::*;
use cleanup;
use cleanup::CleanupMethods;
use common::*;
use datum;
use debuginfo::DebugLoc;
use glue;
use machine;
Expand All @@ -69,6 +64,12 @@ use type_::Type;
use type_of;
use value::Value;

#[derive(Copy, Clone, PartialEq)]
pub enum BranchKind {
Switch,
Single
}

type Hint = attr::ReprAttr;

// Representation of the context surrounding an unsized type. I want
Expand Down Expand Up @@ -178,14 +179,6 @@ impl MaybeSizedValue {
}
}

/// Convenience for `represent_type`. There should probably be more or
/// these, for places in trans where the `Ty` isn't directly
/// available.
pub fn represent_node<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
node: ast::NodeId) -> Rc<Repr<'tcx>> {
represent_type(bcx.ccx(), node_id_type(bcx, node))
}

/// Decides how to represent a given type.
pub fn represent_type<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
t: Ty<'tcx>)
Expand All @@ -201,49 +194,15 @@ pub fn represent_type<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
repr
}

const fn repeat_u8_as_u32(val: u8) -> u32 {
(val as u32) << 24 | (val as u32) << 16 | (val as u32) << 8 | val as u32
}

const fn repeat_u8_as_u64(val: u8) -> u64 {
(repeat_u8_as_u32(val) as u64) << 32 | repeat_u8_as_u32(val) as u64
}

/// `DTOR_NEEDED_HINT` is a stack-local hint that just means
/// "we do not know whether the destructor has run or not; check the
/// drop-flag embedded in the value itself."
pub const DTOR_NEEDED_HINT: u8 = 0x3d;

/// `DTOR_MOVED_HINT` is a stack-local hint that means "this value has
/// definitely been moved; you do not need to run its destructor."
///
/// (However, for now, such values may still end up being explicitly
/// zeroed by the generated code; this is the distinction between
/// `datum::DropFlagInfo::ZeroAndMaintain` versus
/// `datum::DropFlagInfo::DontZeroJustUse`.)
pub const DTOR_MOVED_HINT: u8 = 0x2d;

pub const DTOR_NEEDED: u8 = 0xd4;
#[allow(dead_code)]
pub const DTOR_NEEDED_U64: u64 = repeat_u8_as_u64(DTOR_NEEDED);

pub const DTOR_DONE: u8 = 0x1d;
#[allow(dead_code)]
pub const DTOR_DONE_U64: u64 = repeat_u8_as_u64(DTOR_DONE);

fn dtor_to_init_u8(dtor: bool) -> u8 {
if dtor { DTOR_NEEDED } else { 0 }
if dtor { 1 } else { 0 }
}

pub trait GetDtorType<'tcx> { fn dtor_type(self) -> Ty<'tcx>; }
impl<'a, 'tcx> GetDtorType<'tcx> for TyCtxt<'a, 'tcx, 'tcx> {
fn dtor_type(self) -> Ty<'tcx> { self.types.u8 }
}

fn dtor_active(flag: u8) -> bool {
flag != 0
}

fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
t: Ty<'tcx>) -> Repr<'tcx> {
match t.sty {
Expand Down Expand Up @@ -873,22 +832,19 @@ fn struct_llfields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, st: &Struct<'tcx>,

/// Obtain a representation of the discriminant sufficient to translate
/// destructuring; this may or may not involve the actual discriminant.
///
/// This should ideally be less tightly tied to `_match`.
pub fn trans_switch<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
r: &Repr<'tcx>,
scrutinee: ValueRef,
range_assert: bool)
-> (_match::BranchKind, Option<ValueRef>) {
-> (BranchKind, Option<ValueRef>) {
match *r {
CEnum(..) | General(..) |
RawNullablePointer { .. } | StructWrappedNullablePointer { .. } => {
(_match::Switch, Some(trans_get_discr(bcx, r, scrutinee, None,
range_assert)))
(BranchKind::Switch, Some(trans_get_discr(bcx, r, scrutinee, None, range_assert)))
}
Univariant(..) => {
// N.B.: Univariant means <= 1 enum variants (*not* == 1 variants).
(_match::Single, None)
(BranchKind::Single, None)
}
}
}
Expand Down Expand Up @@ -1001,21 +957,12 @@ pub fn trans_set_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
Store(bcx, C_integral(ll_inttype(bcx.ccx(), ity), discr.0, true),
val);
}
General(ity, ref cases, dtor) => {
if dtor_active(dtor) {
let ptr = trans_field_ptr(bcx, r, MaybeSizedValue::sized(val), discr,
cases[discr.0 as usize].fields.len() - 2);
Store(bcx, C_u8(bcx.ccx(), DTOR_NEEDED), ptr);
}
General(ity, _, _) => {
Store(bcx, C_integral(ll_inttype(bcx.ccx(), ity), discr.0, true),
StructGEP(bcx, val, 0));
}
Univariant(ref st, dtor) => {
Univariant(_, _) => {
assert_eq!(discr, Disr(0));
if dtor_active(dtor) {
Store(bcx, C_u8(bcx.ccx(), DTOR_NEEDED),
StructGEP(bcx, val, st.fields.len() - 1));
}
}
RawNullablePointer { nndiscr, nnty, ..} => {
if discr != nndiscr {
Expand Down Expand Up @@ -1046,28 +993,6 @@ fn assert_discr_in_range(ity: IntType, min: Disr, max: Disr, discr: Disr) {
}
}

/// The number of fields in a given case; for use when obtaining this
/// information from the type or definition is less convenient.
pub fn num_args(r: &Repr, discr: Disr) -> usize {
match *r {
CEnum(..) => 0,
Univariant(ref st, dtor) => {
assert_eq!(discr, Disr(0));
st.fields.len() - (if dtor_active(dtor) { 1 } else { 0 })
}
General(_, ref cases, dtor) => {
cases[discr.0 as usize].fields.len() - 1 - (if dtor_active(dtor) { 1 } else { 0 })
}
RawNullablePointer { nndiscr, ref nullfields, .. } => {
if discr == nndiscr { 1 } else { nullfields.len() }
}
StructWrappedNullablePointer { ref nonnull, nndiscr,
ref nullfields, .. } => {
if discr == nndiscr { nonnull.fields.len() } else { nullfields.len() }
}
}
}

/// Access a field, at a point when the value's case is known.
pub fn trans_field_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
val: MaybeSizedValue, discr: Disr, ix: usize) -> ValueRef {
Expand Down Expand Up @@ -1218,108 +1143,6 @@ fn struct_field_ptr<'blk, 'tcx>(bcx: &BlockAndBuilder<'blk, 'tcx>,
bcx.pointercast(byte_ptr, ll_fty.ptr_to())
}

pub fn fold_variants<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
r: &Repr<'tcx>,
value: ValueRef,
mut f: F)
-> Block<'blk, 'tcx> where
F: FnMut(Block<'blk, 'tcx>, &Struct<'tcx>, ValueRef) -> Block<'blk, 'tcx>,
{
let fcx = bcx.fcx;
match *r {
Univariant(ref st, _) => {
f(bcx, st, value)
}
General(ity, ref cases, _) => {
let ccx = bcx.ccx();

// See the comments in trans/base.rs for more information (inside
// iter_structural_ty), but the gist here is that if the enum's
// discriminant is *not* in the range that we're expecting (in which
// case we'll take the fall-through branch on the switch
// instruction) then we can't just optimize this to an Unreachable
// block.
//
// Currently we still have filling drop, so this means that the drop
// glue for enums may be called when the enum has been paved over
// with the "I've been dropped" value. In this case the default
// branch of the switch instruction will actually be taken at
// runtime, so the basic block isn't actually unreachable, so we
// need to make it do something with defined behavior. In this case
// we just return early from the function.
//
// Note that this is also why the `trans_get_discr` below has
// `false` to indicate that loading the discriminant should
// not have a range assert.
let ret_void_cx = fcx.new_temp_block("enum-variant-iter-ret-void");
RetVoid(ret_void_cx, DebugLoc::None);

let discr_val = trans_get_discr(bcx, r, value, None, false);
let llswitch = Switch(bcx, discr_val, ret_void_cx.llbb, cases.len());
let bcx_next = fcx.new_temp_block("enum-variant-iter-next");

for (discr, case) in cases.iter().enumerate() {
let mut variant_cx = fcx.new_temp_block(
&format!("enum-variant-iter-{}", &discr.to_string())
);
let rhs_val = C_integral(ll_inttype(ccx, ity), discr as u64, true);
AddCase(llswitch, rhs_val, variant_cx.llbb);

let fields = case.fields.iter().map(|&ty|
type_of::type_of(bcx.ccx(), ty)).collect::<Vec<_>>();
let real_ty = Type::struct_(ccx, &fields[..], case.packed);
let variant_value = PointerCast(variant_cx, value, real_ty.ptr_to());

variant_cx = f(variant_cx, case, variant_value);
Br(variant_cx, bcx_next.llbb, DebugLoc::None);
}

bcx_next
}
_ => bug!()
}
}

/// Access the struct drop flag, if present.
pub fn trans_drop_flag_ptr<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
r: &Repr<'tcx>,
val: ValueRef)
-> datum::DatumBlock<'blk, 'tcx, datum::Expr>
{
let tcx = bcx.tcx();
let ptr_ty = bcx.tcx().mk_imm_ptr(tcx.dtor_type());
match *r {
Univariant(ref st, dtor) if dtor_active(dtor) => {
let flag_ptr = StructGEP(bcx, val, st.fields.len() - 1);
datum::immediate_rvalue_bcx(bcx, flag_ptr, ptr_ty).to_expr_datumblock()
}
General(_, _, dtor) if dtor_active(dtor) => {
let fcx = bcx.fcx;
let custom_cleanup_scope = fcx.push_custom_cleanup_scope();
let scratch = unpack_datum!(bcx, datum::lvalue_scratch_datum(
bcx, tcx.dtor_type(), "drop_flag",
InitAlloca::Uninit("drop flag itself has no dtor"),
cleanup::CustomScope(custom_cleanup_scope), |bcx, _| {
debug!("no-op populate call for trans_drop_flag_ptr on dtor_type={:?}",
tcx.dtor_type());
bcx
}
));
bcx = fold_variants(bcx, r, val, |variant_cx, st, value| {
let ptr = struct_field_ptr(&variant_cx.build(), st,
MaybeSizedValue::sized(value),
(st.fields.len() - 1), false);
datum::Datum::new(ptr, ptr_ty, datum::Lvalue::new("adt::trans_drop_flag_ptr"))
.store_to(variant_cx, scratch.val)
});
let expr_datum = scratch.to_expr_datum();
fcx.pop_custom_cleanup_scope(custom_cleanup_scope);
datum::DatumBlock::new(bcx, expr_datum)
}
_ => bug!("tried to get drop flag of non-droppable type")
}
}

/// Construct a constant value, suitable for initializing a
/// GlobalVariable, given a case and constant values for its fields.
/// Note that this may have a different LLVM type (and different
Expand Down Expand Up @@ -1458,28 +1281,6 @@ fn padding(ccx: &CrateContext, size: u64) -> ValueRef {
#[inline]
fn roundup(x: u64, a: u32) -> u64 { let a = a as u64; ((x + (a - 1)) / a) * a }

/// Get the discriminant of a constant value.
pub fn const_get_discrim(r: &Repr, val: ValueRef) -> Disr {
match *r {
CEnum(ity, _, _) => {
match ity {
attr::SignedInt(..) => Disr(const_to_int(val) as u64),
attr::UnsignedInt(..) => Disr(const_to_uint(val)),
}
}
General(ity, _, _) => {
match ity {
attr::SignedInt(..) => Disr(const_to_int(const_get_elt(val, &[0])) as u64),
attr::UnsignedInt(..) => Disr(const_to_uint(const_get_elt(val, &[0])))
}
}
Univariant(..) => Disr(0),
RawNullablePointer { .. } | StructWrappedNullablePointer { .. } => {
bug!("const discrim access of non c-like enum")
}
}
}

/// Extract a field of a constant value, as appropriate for its
/// representation.
///
Expand Down
19 changes: 10 additions & 9 deletions src/librustc_trans/asm.rs
Expand Up @@ -14,28 +14,29 @@ use llvm::{self, ValueRef};
use base;
use build::*;
use common::*;
use datum::{Datum, Lvalue};
use type_of;
use type_::Type;

use rustc::hir as ast;
use rustc::hir;
use rustc::ty::Ty;

use std::ffi::CString;
use syntax::ast::AsmDialect;
use libc::{c_uint, c_char};

// Take an inline assembly expression and splat it out via LLVM
pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
ia: &ast::InlineAsm,
outputs: Vec<Datum<'tcx, Lvalue>>,
ia: &hir::InlineAsm,
outputs: Vec<(ValueRef, Ty<'tcx>)>,
mut inputs: Vec<ValueRef>) {
let mut ext_constraints = vec![];
let mut output_types = vec![];

// Prepare the output operands
let mut indirect_outputs = vec![];
for (i, (out, out_datum)) in ia.outputs.iter().zip(&outputs).enumerate() {
for (i, (out, &(val, ty))) in ia.outputs.iter().zip(&outputs).enumerate() {
let val = if out.is_rw || out.is_indirect {
Some(base::load_ty(bcx, out_datum.val, out_datum.ty))
Some(base::load_ty(bcx, val, ty))
} else {
None
};
Expand All @@ -46,7 +47,7 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
if out.is_indirect {
indirect_outputs.push(val.unwrap());
} else {
output_types.push(type_of::type_of(bcx.ccx(), out_datum.ty));
output_types.push(type_of::type_of(bcx.ccx(), ty));
}
}
if !indirect_outputs.is_empty() {
Expand Down Expand Up @@ -100,9 +101,9 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,

// Again, based on how many outputs we have
let outputs = ia.outputs.iter().zip(&outputs).filter(|&(ref o, _)| !o.is_indirect);
for (i, (_, datum)) in outputs.enumerate() {
for (i, (_, &(val, _))) in outputs.enumerate() {
let v = if num_outputs == 1 { r } else { ExtractValue(bcx, r, i) };
Store(bcx, v, datum.val);
Store(bcx, v, val);
}

// Store expn_id in a metadata node so we can map LLVM errors
Expand Down

0 comments on commit d0654ae

Please sign in to comment.