Skip to content
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

emit !align attributes on stores of operand pairs #40385

Merged
merged 1 commit into from
Mar 13, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions src/librustc_trans/mir/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -833,8 +833,21 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
self.trans_lvalue(bcx, dest)
};
if fn_ret_ty.is_indirect() {
llargs.push(dest.llval);
ReturnDest::Nothing
match dest.alignment {
Alignment::AbiAligned => {
llargs.push(dest.llval);
ReturnDest::Nothing
},
Alignment::Packed => {
// Currently, MIR code generation does not create calls
// that store directly to fields of packed structs (in
// fact, the calls it creates write only to temps),
//
// If someone changes that, please update this code path
// to create a temporary.
span_bug!(self.mir.span, "can't directly store to unaligned value");
}
}
} else {
ReturnDest::Store(dest.llval)
}
Expand Down
11 changes: 9 additions & 2 deletions src/librustc_trans/mir/operand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,10 +268,17 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
bcx.store(base::from_immediate(bcx, s), lldest, align);
}
OperandValue::Pair(a, b) => {
let f_align = match *bcx.ccx.layout_of(operand.ty) {
Layout::Univariant { ref variant, .. } if variant.packed => {
Some(1)
}
_ => align
};

let a = base::from_immediate(bcx, a);
let b = base::from_immediate(bcx, b);
bcx.store(a, bcx.struct_gep(lldest, 0), align);
bcx.store(b, bcx.struct_gep(lldest, 1), align);
bcx.store(a, bcx.struct_gep(lldest, 0), f_align);
bcx.store(b, bcx.struct_gep(lldest, 1), f_align);
}
}
}
Expand Down
33 changes: 33 additions & 0 deletions src/test/codegen/packed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,36 @@ pub fn write_pkd(pkd: &mut Packed) -> u32 {
pkd.data = 42;
result
}

pub struct Array([i32; 8]);
#[repr(packed)]
pub struct BigPacked {
dealign: u8,
data: Array
}

// CHECK-LABEL: @call_pkd
#[no_mangle]
pub fn call_pkd(f: fn() -> Array) -> BigPacked {
// CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca %Array
// CHECK: call void %{{.*}}(%Array* noalias nocapture sret dereferenceable(32) [[ALLOCA]])
// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* %{{.*}}, i{{[0-9]+}} 32, i32 1, i1 false)
// check that calls whose destination is a field of a packed struct
// go through an alloca rather than calling the function with an
// unaligned destination.
BigPacked { dealign: 0, data: f() }
}

#[repr(packed)]
#[derive(Copy, Clone)]
pub struct PackedPair(u8, u32);

// CHECK-LABEL: @pkd_pair
#[no_mangle]
pub fn pkd_pair(pair1: &mut PackedPair, pair2: &mut PackedPair) {
// CHECK: [[V1:%[a-z0-9]+]] = load i8, i8* %{{.*}}, align 1
// CHECK: [[V2:%[a-z0-9]+]] = load i32, i32* %{{.*}}, align 1
// CHECK: store i8 [[V1]], i8* {{.*}}, align 1
// CHECK: store i32 [[V2]], i32* {{.*}}, align 1
*pair2 = *pair1;
}