Skip to content

Commit 1477119

Browse files
committed
rustc_trans: keep a layout instead of a type in {Lvalue,Operand}Ref.
1 parent 88f7032 commit 1477119

File tree

17 files changed

+374
-414
lines changed

17 files changed

+374
-414
lines changed

src/librustc/ty/layout.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,15 @@ impl Abi {
771771
}
772772
}
773773

774+
/// Returns true if the type is a ZST and not unsized.
775+
pub fn is_zst(&self) -> bool {
776+
match *self {
777+
Abi::Scalar(_) => false,
778+
Abi::Vector { count, .. } => count == 0,
779+
Abi::Aggregate { sized, size, .. } => sized && size.bytes() == 0
780+
}
781+
}
782+
774783
pub fn size<C: HasDataLayout>(&self, cx: C) -> Size {
775784
let dl = cx.data_layout();
776785

@@ -1377,7 +1386,7 @@ impl<'a, 'tcx> Layout {
13771386
no_explicit_discriminants {
13781387
// Nullable pointer optimization
13791388
for i in 0..2 {
1380-
if !variants[1 - i].iter().all(|f| f.size(dl).bytes() == 0) {
1389+
if !variants[1 - i].iter().all(|f| f.is_zst()) {
13811390
continue;
13821391
}
13831392

@@ -1456,7 +1465,7 @@ impl<'a, 'tcx> Layout {
14561465
for i in st.fields.index_by_increasing_offset() {
14571466
let field = field_layouts[i];
14581467
let field_align = field.align(dl);
1459-
if field.size(dl).bytes() != 0 || field_align.abi() != 1 {
1468+
if !field.is_zst() || field_align.abi() != 1 {
14601469
start_align = start_align.min(field_align);
14611470
break;
14621471
}
@@ -2145,6 +2154,11 @@ impl<'a, 'tcx> FullLayout<'tcx> {
21452154
self.abi.is_packed()
21462155
}
21472156

2157+
/// Returns true if the type is a ZST and not unsized.
2158+
pub fn is_zst(&self) -> bool {
2159+
self.abi.is_zst()
2160+
}
2161+
21482162
pub fn size<C: HasDataLayout>(&self, cx: C) -> Size {
21492163
self.abi.size(cx)
21502164
}

src/librustc_trans/abi.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -697,7 +697,7 @@ impl<'a, 'tcx> FnType<'tcx> {
697697
if ty.is_bool() {
698698
arg.attrs.set(ArgAttribute::ZExt);
699699
} else {
700-
if arg.layout.size(ccx).bytes() == 0 {
700+
if arg.layout.is_zst() {
701701
// For some forsaken reason, x86_64-pc-windows-gnu
702702
// doesn't ignore zero-sized struct arguments.
703703
// The same is true for s390x-unknown-linux-gnu.

src/librustc_trans/asm.rs

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,9 @@ use type_::Type;
1616
use builder::Builder;
1717

1818
use rustc::hir;
19-
use rustc::ty::Ty;
20-
use rustc::ty::layout::Align;
2119

22-
use mir::lvalue::{LvalueRef, Alignment};
20+
use mir::lvalue::LvalueRef;
21+
use mir::operand::OperandValue;
2322

2423
use std::ffi::CString;
2524
use syntax::ast::AsmDialect;
@@ -29,29 +28,23 @@ use libc::{c_uint, c_char};
2928
pub fn trans_inline_asm<'a, 'tcx>(
3029
bcx: &Builder<'a, 'tcx>,
3130
ia: &hir::InlineAsm,
32-
outputs: Vec<(ValueRef, Ty<'tcx>)>,
31+
outputs: Vec<LvalueRef<'tcx>>,
3332
mut inputs: Vec<ValueRef>
3433
) {
3534
let mut ext_constraints = vec![];
3635
let mut output_types = vec![];
3736

3837
// Prepare the output operands
3938
let mut indirect_outputs = vec![];
40-
for (i, (out, &(val, ty))) in ia.outputs.iter().zip(&outputs).enumerate() {
41-
let val = if out.is_rw || out.is_indirect {
42-
Some(LvalueRef::new_sized(val, ty,
43-
Alignment::Packed(Align::from_bytes(1, 1).unwrap())).load(bcx))
44-
} else {
45-
None
46-
};
39+
for (i, (out, lvalue)) in ia.outputs.iter().zip(&outputs).enumerate() {
4740
if out.is_rw {
48-
inputs.push(val.unwrap().immediate());
41+
inputs.push(lvalue.load(bcx).immediate());
4942
ext_constraints.push(i.to_string());
5043
}
5144
if out.is_indirect {
52-
indirect_outputs.push(val.unwrap().immediate());
45+
indirect_outputs.push(lvalue.load(bcx).immediate());
5346
} else {
54-
output_types.push(bcx.ccx.llvm_type_of(ty));
47+
output_types.push(bcx.ccx.llvm_type_of(lvalue.layout.ty));
5548
}
5649
}
5750
if !indirect_outputs.is_empty() {
@@ -106,9 +99,9 @@ pub fn trans_inline_asm<'a, 'tcx>(
10699

107100
// Again, based on how many outputs we have
108101
let outputs = ia.outputs.iter().zip(&outputs).filter(|&(ref o, _)| !o.is_indirect);
109-
for (i, (_, &(val, _))) in outputs.enumerate() {
102+
for (i, (_, &lvalue)) in outputs.enumerate() {
110103
let v = if num_outputs == 1 { r } else { bcx.extract_value(r, i as u64) };
111-
bcx.store(v, val, None);
104+
OperandValue::Immediate(v).store(bcx, lvalue);
112105
}
113106

114107
// Store mark in a metadata node so we can map LLVM errors

src/librustc_trans/base.rs

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ use rustc::middle::lang_items::StartFnLangItem;
4040
use rustc::middle::trans::{Linkage, Visibility, Stats};
4141
use rustc::middle::cstore::{EncodedMetadata, EncodedMetadataHashes};
4242
use rustc::ty::{self, Ty, TyCtxt};
43-
use rustc::ty::layout::Align;
43+
use rustc::ty::layout::{Align, FullLayout};
4444
use rustc::ty::maps::Providers;
4545
use rustc::dep_graph::{DepNode, DepKind, DepConstructor};
4646
use rustc::middle::cstore::{self, LinkMeta, LinkagePreference};
@@ -55,10 +55,7 @@ use builder::Builder;
5555
use callee;
5656
use common::{C_bool, C_bytes_in_context, C_i32, C_usize};
5757
use collector::{self, TransItemCollectionMode};
58-
use common::{C_struct_in_context, C_array};
59-
use common::CrateContext;
60-
use common::{type_is_zero_size, val_ty};
61-
use common;
58+
use common::{self, C_struct_in_context, C_array, CrateContext, val_ty};
6259
use consts;
6360
use context::{self, LocalCrateContext, SharedCrateContext};
6461
use debuginfo;
@@ -88,7 +85,7 @@ use syntax::attr;
8885
use rustc::hir;
8986
use syntax::ast;
9087

91-
use mir::operand::{OperandRef, OperandValue};
88+
use mir::operand::OperandValue;
9289

9390
pub use rustc_trans_utils::{find_exported_symbols, check_for_rustc_errors_attr};
9491
pub use rustc_trans_utils::trans_item::linkage_by_name;
@@ -249,8 +246,8 @@ pub fn unsize_thin_ptr<'a, 'tcx>(
249246
pub fn coerce_unsized_into<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
250247
src: LvalueRef<'tcx>,
251248
dst: LvalueRef<'tcx>) {
252-
let src_ty = src.ty.to_ty(bcx.tcx());
253-
let dst_ty = dst.ty.to_ty(bcx.tcx());
249+
let src_ty = src.layout.ty;
250+
let dst_ty = dst.layout.ty;
254251
let coerce_ptr = || {
255252
let (base, info) = match src.load(bcx).val {
256253
OperandValue::Pair(base, info) => {
@@ -266,10 +263,7 @@ pub fn coerce_unsized_into<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
266263
}
267264
OperandValue::Ref(..) => bug!()
268265
};
269-
OperandRef {
270-
val: OperandValue::Pair(base, info),
271-
ty: dst_ty
272-
}.store(bcx, dst);
266+
OperandValue::Pair(base, info).store(bcx, dst);
273267
};
274268
match (&src_ty.sty, &dst_ty.sty) {
275269
(&ty::TyRef(..), &ty::TyRef(..)) |
@@ -288,15 +282,12 @@ pub fn coerce_unsized_into<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
288282
let src_f = src.project_field(bcx, i);
289283
let dst_f = dst.project_field(bcx, i);
290284

291-
let src_f_ty = src_f.ty.to_ty(bcx.tcx());
292-
let dst_f_ty = dst_f.ty.to_ty(bcx.tcx());
293-
294-
if type_is_zero_size(bcx.ccx, dst_f_ty) {
285+
if dst_f.layout.is_zst() {
295286
continue;
296287
}
297288

298-
if src_f_ty == dst_f_ty {
299-
memcpy_ty(bcx, dst_f.llval, src_f.llval, src_f_ty,
289+
if src_f.layout.ty == dst_f.layout.ty {
290+
memcpy_ty(bcx, dst_f.llval, src_f.llval, src_f.layout,
300291
(src_f.alignment | dst_f.alignment).non_abi());
301292
} else {
302293
coerce_unsized_into(bcx, src_f, dst_f);
@@ -409,17 +400,17 @@ pub fn memcpy_ty<'a, 'tcx>(
409400
bcx: &Builder<'a, 'tcx>,
410401
dst: ValueRef,
411402
src: ValueRef,
412-
t: Ty<'tcx>,
403+
layout: FullLayout<'tcx>,
413404
align: Option<Align>,
414405
) {
415406
let ccx = bcx.ccx;
416407

417-
let size = ccx.size_of(t).bytes();
408+
let size = layout.size(ccx).bytes();
418409
if size == 0 {
419410
return;
420411
}
421412

422-
let align = align.unwrap_or_else(|| ccx.align_of(t));
413+
let align = align.unwrap_or_else(|| layout.align(ccx));
423414
call_memcpy(bcx, dst, src, C_usize(ccx, size), align);
424415
}
425416

src/librustc_trans/cabi_x86_64.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ fn classify_arg<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, arg: &ArgType<'tcx>)
5858
off: Size)
5959
-> Result<(), Memory> {
6060
if !off.is_abi_aligned(layout.align(ccx)) {
61-
if layout.size(ccx).bytes() > 0 {
61+
if !layout.is_zst() {
6262
return Err(Memory);
6363
}
6464
return Ok(());

src/librustc_trans/common.rs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,7 @@ pub fn type_is_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -
5858
match layout.abi {
5959
layout::Abi::Scalar(_) | layout::Abi::Vector { .. } => true,
6060

61-
layout::Abi::Aggregate { .. } => {
62-
!layout.is_unsized() && layout.size(ccx).bytes() == 0
63-
}
61+
layout::Abi::Aggregate { .. } => layout.is_zst()
6462
}
6563
}
6664

@@ -83,12 +81,6 @@ pub fn type_is_imm_pair<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>)
8381
}
8482
}
8583

86-
/// Identify types which have size zero at runtime.
87-
pub fn type_is_zero_size<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
88-
let layout = ccx.layout_of(ty);
89-
!layout.is_unsized() && layout.size(ccx).bytes() == 0
90-
}
91-
9284
pub fn type_needs_drop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bool {
9385
ty.needs_drop(tcx, ty::ParamEnv::empty(traits::Reveal::All))
9486
}

src/librustc_trans/debuginfo/mod.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -335,8 +335,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
335335
signature.extend(inputs.iter().map(|&t| {
336336
let t = match t.sty {
337337
ty::TyArray(ct, _)
338-
if (ct == cx.tcx().types.u8) ||
339-
(cx.layout_of(ct).size(cx).bytes() == 0) => {
338+
if (ct == cx.tcx().types.u8) || cx.layout_of(ct).is_zst() => {
340339
cx.tcx().mk_imm_ptr(ct)
341340
}
342341
_ => t

src/librustc_trans/intrinsic.rs

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use declare;
2222
use glue;
2323
use type_::Type;
2424
use rustc::ty::{self, Ty};
25-
use rustc::ty::layout::HasDataLayout;
25+
use rustc::ty::layout::{HasDataLayout, LayoutOf};
2626
use rustc::hir;
2727
use syntax::ast;
2828
use syntax::symbol::Symbol;
@@ -86,7 +86,7 @@ fn get_simple_intrinsic(ccx: &CrateContext, name: &str) -> Option<ValueRef> {
8686
/// add them to librustc_trans/trans/context.rs
8787
pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
8888
callee_ty: Ty<'tcx>,
89-
fn_ty: &FnType,
89+
fn_ty: &FnType<'tcx>,
9090
args: &[OperandRef<'tcx>],
9191
llresult: ValueRef,
9292
span: Span) {
@@ -105,7 +105,7 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
105105
let name = &*tcx.item_name(def_id);
106106

107107
let llret_ty = ccx.llvm_type_of(ret_ty);
108-
let result = LvalueRef::new_sized(llresult, ret_ty, Alignment::AbiAligned);
108+
let result = LvalueRef::new_sized(llresult, fn_ty.ret.layout, Alignment::AbiAligned);
109109

110110
let simple = get_simple_intrinsic(ccx, name);
111111
let llval = match name {
@@ -179,7 +179,7 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
179179
}
180180
"init" => {
181181
let ty = substs.type_at(0);
182-
if !type_is_zero_size(ccx, ty) {
182+
if !ccx.layout_of(ty).is_zst() {
183183
// Just zero out the stack slot.
184184
// If we store a zero constant, LLVM will drown in vreg allocation for large data
185185
// structures, and the generated code will be awful. (A telltale sign of this is
@@ -247,15 +247,15 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
247247
},
248248
"volatile_store" => {
249249
let tp_ty = substs.type_at(0);
250-
let dst = LvalueRef::new_sized(args[0].immediate(), tp_ty, Alignment::AbiAligned);
250+
let dst = args[0].deref(bcx.ccx);
251251
if let OperandValue::Pair(a, b) = args[1].val {
252252
bcx.volatile_store(a, dst.project_field(bcx, 0).llval);
253253
bcx.volatile_store(b, dst.project_field(bcx, 1).llval);
254254
} else {
255255
let val = if let OperandValue::Ref(ptr, align) = args[1].val {
256256
bcx.load(ptr, align.non_abi())
257257
} else {
258-
if type_is_zero_size(ccx, tp_ty) {
258+
if dst.layout.is_zst() {
259259
return;
260260
}
261261
from_immediate(bcx, args[1].immediate())
@@ -393,13 +393,9 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
393393
},
394394

395395
"discriminant_value" => {
396-
let val_ty = substs.type_at(0);
397-
let adt_val = LvalueRef::new_sized(args[0].immediate(),
398-
val_ty,
399-
Alignment::AbiAligned);
400-
match val_ty.sty {
396+
match substs.type_at(0).sty {
401397
ty::TyAdt(adt, ..) if adt.is_enum() => {
402-
adt_val.trans_get_discr(bcx, ret_ty)
398+
args[0].deref(bcx.ccx).trans_get_discr(bcx, ret_ty)
403399
}
404400
_ => C_null(llret_ty)
405401
}
@@ -612,12 +608,12 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
612608
// This assumes the type is "simple", i.e. no
613609
// destructors, and the contents are SIMD
614610
// etc.
615-
assert!(!bcx.ccx.shared().type_needs_drop(arg.ty));
611+
assert!(!bcx.ccx.shared().type_needs_drop(arg.layout.ty));
616612
let (ptr, align) = match arg.val {
617613
OperandValue::Ref(ptr, align) => (ptr, align),
618614
_ => bug!()
619615
};
620-
let arg = LvalueRef::new_sized(ptr, arg.ty, align);
616+
let arg = LvalueRef::new_sized(ptr, arg.layout, align);
621617
(0..contents.len()).map(|i| {
622618
arg.project_field(bcx, i).load(bcx).immediate()
623619
}).collect()
@@ -685,8 +681,8 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
685681
} else {
686682
OperandRef {
687683
val: OperandValue::Immediate(llval),
688-
ty: ret_ty
689-
}.unpack_if_pair(bcx).store(bcx, result);
684+
layout: result.layout
685+
}.unpack_if_pair(bcx).val.store(bcx, result);
690686
}
691687
}
692688
}

src/librustc_trans/mir/analyze.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use rustc::mir::{self, Location, TerminatorKind, Literal};
1818
use rustc::mir::visit::{Visitor, LvalueContext};
1919
use rustc::mir::traversal;
2020
use rustc::ty;
21+
use rustc::ty::layout::LayoutOf;
2122
use common;
2223
use super::MirContext;
2324

@@ -34,7 +35,7 @@ pub fn lvalue_locals<'a, 'tcx>(mircx: &MirContext<'a, 'tcx>) -> BitVector {
3435
ty.is_box() ||
3536
ty.is_region_ptr() ||
3637
ty.is_simd() ||
37-
common::type_is_zero_size(mircx.ccx, ty)
38+
mircx.ccx.layout_of(ty).is_zst()
3839
{
3940
// These sorts of types are immediates that we can store
4041
// in an ValueRef without an alloca.

0 commit comments

Comments
 (0)