Skip to content

Implement Unsized Rvalues #51131

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Aug 19, 2018
Prev Previous commit
Next Next commit
Integrate PassMode::UnsizedIndirect into PassMode::Indirect.
  • Loading branch information
qnighy committed Aug 18, 2018
commit 6e15e7c1267e26d2bab3d0ded8454a2a45669d55
33 changes: 15 additions & 18 deletions src/librustc_codegen_llvm/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
return;
}
let cx = bx.cx;
if self.is_indirect() {
if self.is_sized_indirect() {
OperandValue::Ref(val, self.layout.align).store(bx, dst)
} else if self.is_unsized_indirect() {
bug!("unsized ArgType must be handled through store_fn_arg");
Expand Down Expand Up @@ -248,10 +248,10 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
PassMode::Pair(..) => {
OperandValue::Pair(next(), next()).store(bx, dst);
}
PassMode::UnsizedIndirect(..) => {
PassMode::Indirect(_, Some(_)) => {
OperandValue::UnsizedRef(next(), next()).store(bx, dst);
}
PassMode::Direct(_) | PassMode::Indirect(_) | PassMode::Cast(_) => {
PassMode::Direct(_) | PassMode::Indirect(_, None) | PassMode::Cast(_) => {
self.store(bx, next(), dst);
}
}
Expand Down Expand Up @@ -547,9 +547,7 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
}

let size = arg.layout.size;
if arg.layout.is_unsized() {
arg.make_unsized_indirect(None);
} else if size > layout::Pointer.size(cx) {
if arg.layout.is_unsized() || size > layout::Pointer.size(cx) {
arg.make_indirect();
} else {
// We want to pass small aggregates as immediates, but using
Expand All @@ -565,7 +563,7 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
for arg in &mut self.args {
fixup(arg);
}
if let PassMode::Indirect(ref mut attrs) = self.ret.mode {
if let PassMode::Indirect(ref mut attrs, _) = self.ret.mode {
attrs.set(ArgAttribute::StructRet);
}
return;
Expand All @@ -582,7 +580,7 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
if let PassMode::Pair(_, _) = arg.mode { 2 } else { 1 }
).sum();
let mut llargument_tys = Vec::with_capacity(
if let PassMode::Indirect(_) = self.ret.mode { 1 } else { 0 } + args_capacity
if let PassMode::Indirect(..) = self.ret.mode { 1 } else { 0 } + args_capacity
);

let llreturn_ty = match self.ret.mode {
Expand All @@ -591,11 +589,10 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
self.ret.layout.immediate_llvm_type(cx)
}
PassMode::Cast(cast) => cast.llvm_type(cx),
PassMode::Indirect(_) => {
PassMode::Indirect(..) => {
llargument_tys.push(self.ret.memory_ty(cx).ptr_to());
Type::void(cx)
}
PassMode::UnsizedIndirect(..) => bug!("return type must be sized"),
};

for arg in &self.args {
Expand All @@ -612,15 +609,15 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(cx, 1, true));
continue;
}
PassMode::UnsizedIndirect(..) => {
PassMode::Indirect(_, Some(_)) => {
let ptr_ty = cx.tcx.mk_mut_ptr(arg.layout.ty);
let ptr_layout = cx.layout_of(ptr_ty);
llargument_tys.push(ptr_layout.scalar_pair_element_llvm_type(cx, 0, true));
llargument_tys.push(ptr_layout.scalar_pair_element_llvm_type(cx, 1, true));
continue;
}
PassMode::Cast(cast) => cast.llvm_type(cx),
PassMode::Indirect(_) => arg.memory_ty(cx).ptr_to(),
PassMode::Indirect(_, None) => arg.memory_ty(cx).ptr_to(),
};
llargument_tys.push(llarg_ty);
}
Expand Down Expand Up @@ -659,7 +656,7 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
PassMode::Direct(ref attrs) => {
attrs.apply_llfn(llvm::AttributePlace::ReturnValue, llfn);
}
PassMode::Indirect(ref attrs) => apply(attrs),
PassMode::Indirect(ref attrs, _) => apply(attrs),
_ => {}
}
for arg in &self.args {
Expand All @@ -669,8 +666,8 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
match arg.mode {
PassMode::Ignore => {}
PassMode::Direct(ref attrs) |
PassMode::Indirect(ref attrs) => apply(attrs),
PassMode::UnsizedIndirect(ref attrs, ref extra_attrs) => {
PassMode::Indirect(ref attrs, None) => apply(attrs),
PassMode::Indirect(ref attrs, Some(ref extra_attrs)) => {
apply(attrs);
apply(extra_attrs);
}
Expand All @@ -693,7 +690,7 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
PassMode::Direct(ref attrs) => {
attrs.apply_callsite(llvm::AttributePlace::ReturnValue, callsite);
}
PassMode::Indirect(ref attrs) => apply(attrs),
PassMode::Indirect(ref attrs, _) => apply(attrs),
_ => {}
}
if let layout::Abi::Scalar(ref scalar) = self.ret.layout.abi {
Expand All @@ -717,8 +714,8 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
match arg.mode {
PassMode::Ignore => {}
PassMode::Direct(ref attrs) |
PassMode::Indirect(ref attrs) => apply(attrs),
PassMode::UnsizedIndirect(ref attrs, ref extra_attrs) => {
PassMode::Indirect(ref attrs, None) => apply(attrs),
PassMode::Indirect(ref attrs, Some(ref extra_attrs)) => {
apply(attrs);
apply(extra_attrs);
}
Expand Down
8 changes: 3 additions & 5 deletions src/librustc_codegen_llvm/mir/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ impl FunctionCx<'a, 'll, 'tcx> {

mir::TerminatorKind::Return => {
let llval = match self.fn_ty.ret.mode {
PassMode::Ignore | PassMode::Indirect(_) => {
PassMode::Ignore | PassMode::Indirect(..) => {
bx.ret_void();
return;
}
Expand Down Expand Up @@ -270,8 +270,6 @@ impl FunctionCx<'a, 'll, 'tcx> {
bx.pointercast(llslot, cast_ty.llvm_type(bx.cx).ptr_to()),
self.fn_ty.ret.layout.align)
}

PassMode::UnsizedIndirect(..) => bug!("return value must be sized"),
};
bx.ret(llval);
}
Expand Down Expand Up @@ -667,7 +665,7 @@ impl FunctionCx<'a, 'll, 'tcx> {
}
_ => bug!("codegen_argument: {:?} invalid for pair arugment", op)
}
} else if let PassMode::UnsizedIndirect(..) = arg.mode {
} else if arg.is_unsized_indirect() {
match op.val {
UnsizedRef(a, b) => {
llargs.push(a);
Expand All @@ -682,7 +680,7 @@ impl FunctionCx<'a, 'll, 'tcx> {
let (mut llval, align, by_ref) = match op.val {
Immediate(_) | Pair(..) => {
match arg.mode {
PassMode::Indirect(_) | PassMode::Cast(_) => {
PassMode::Indirect(..) | PassMode::Cast(_) => {
let scratch = PlaceRef::alloca(bx, arg.layout, "arg");
op.val.store(bx, scratch);
(scratch.llval, scratch.align, true)
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_codegen_llvm/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,7 @@ fn arg_local_refs(
}
}

let place = if arg.is_indirect() {
let place = if arg.is_sized_indirect() {
// Don't copy an indirect argument to an alloca, the caller
// already put it in a temporary alloca and gave it up.
// FIXME: lifetimes
Expand Down
48 changes: 21 additions & 27 deletions src/librustc_target/abi/call/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ pub enum PassMode {
/// a single uniform or a pair of registers.
Cast(CastTarget),
/// Pass the argument indirectly via a hidden pointer.
Indirect(ArgAttributes),
/// Pass the unsized argument indirectly via a hidden pointer.
UnsizedIndirect(ArgAttributes, ArgAttributes),
/// The second value, if any, is for the extra data (vtable or length)
/// which indicates that it refers to an unsized rvalue.
Indirect(ArgAttributes, Option<ArgAttributes>),
}

// Hack to disable non_upper_case_globals only for the bitflags! and not for the rest
Expand Down Expand Up @@ -370,38 +370,25 @@ impl<'a, Ty> ArgType<'a, Ty> {
// i686-pc-windows-msvc, it results in wrong stack offsets.
// attrs.pointee_align = Some(self.layout.align);

self.mode = PassMode::Indirect(attrs);
let extra_attrs = if self.layout.is_unsized() {
Some(ArgAttributes::new())
} else {
None
};

self.mode = PassMode::Indirect(attrs, extra_attrs);
}

pub fn make_indirect_byval(&mut self) {
self.make_indirect();
match self.mode {
PassMode::Indirect(ref mut attrs) => {
PassMode::Indirect(ref mut attrs, _) => {
attrs.set(ArgAttribute::ByVal);
}
_ => unreachable!()
}
}

pub fn make_unsized_indirect(&mut self, vtable_size: Option<Size>) {
self.make_indirect();

let attrs = if let PassMode::Indirect(attrs) = self.mode {
attrs
} else {
unreachable!()
};

let mut extra_attrs = ArgAttributes::new();
if let Some(vtable_size) = vtable_size {
extra_attrs.set(ArgAttribute::NoAlias)
.set(ArgAttribute::NonNull);
extra_attrs.pointee_size = vtable_size;
}

self.mode = PassMode::UnsizedIndirect(attrs, extra_attrs);
}

pub fn extend_integer_width_to(&mut self, bits: u64) {
// Only integers have signedness
if let Abi::Scalar(ref scalar) = self.layout.abi {
Expand Down Expand Up @@ -430,14 +417,21 @@ impl<'a, Ty> ArgType<'a, Ty> {

pub fn is_indirect(&self) -> bool {
match self.mode {
PassMode::Indirect(_) => true,
PassMode::Indirect(..) => true,
_ => false
}
}

pub fn is_sized_indirect(&self) -> bool {
match self.mode {
PassMode::Indirect(_, None) => true,
_ => false
}
}

pub fn is_unsized_indirect(&self) -> bool {
match self.mode {
PassMode::UnsizedIndirect(..) => true,
PassMode::Indirect(_, Some(_)) => true,
_ => false
}
}
Expand Down Expand Up @@ -534,7 +528,7 @@ impl<'a, Ty> FnType<'a, Ty> {
a => return Err(format!("unrecognized arch \"{}\" in target specification", a))
}

if let PassMode::Indirect(ref mut attrs) = self.ret.mode {
if let PassMode::Indirect(ref mut attrs, _) = self.ret.mode {
attrs.set(ArgAttribute::StructRet);
}

Expand Down
4 changes: 2 additions & 2 deletions src/librustc_target/abi/call/x86.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,10 @@ pub fn compute_abi_info<'a, Ty, C>(cx: C, fty: &mut FnType<'a, Ty>, flavor: Flav
for arg in &mut fty.args {
let attrs = match arg.mode {
PassMode::Ignore |
PassMode::Indirect(_) => continue,
PassMode::Indirect(_, None) => continue,
PassMode::Direct(ref mut attrs) => attrs,
PassMode::Pair(..) |
PassMode::UnsizedIndirect(..) |
PassMode::Indirect(_, Some(_)) |
PassMode::Cast(_) => {
unreachable!("x86 shouldn't be passing arguments by {:?}", arg.mode)
}
Expand Down