Skip to content

Commit 0166f4a

Browse files
author
bors-servo
authored
Auto merge of #1289 - emilio:target-stuff, r=fitzgen
codegen: Use target pointer size consistently for layout calculations Assuming new enough libclang, this PR makes cross-compilation do layout calculations properly. Fixes #1284
2 parents 5b8572f + de0d850 commit 0166f4a

27 files changed

+685
-98
lines changed

.travis.yml

+23-19
Original file line numberDiff line numberDiff line change
@@ -10,29 +10,33 @@ env:
1010
global:
1111
- CARGO_TARGET_DIR=/tmp/bindgen
1212
matrix:
13-
- LLVM_VERSION="3.8.1" BINDGEN_JOB="test" BINDGEN_PROFILE=
14-
- LLVM_VERSION="3.8.1" BINDGEN_JOB="test" BINDGEN_PROFILE="--release"
15-
- LLVM_VERSION="3.8.1" BINDGEN_JOB="integration" BINDGEN_PROFILE=
16-
- LLVM_VERSION="3.8.1" BINDGEN_JOB="integration" BINDGEN_PROFILE="--release"
17-
- LLVM_VERSION="3.9.0" BINDGEN_JOB="test" BINDGEN_PROFILE=
18-
- LLVM_VERSION="3.9.0" BINDGEN_JOB="test" BINDGEN_PROFILE="--release"
19-
- LLVM_VERSION="3.9.0" BINDGEN_JOB="integration" BINDGEN_PROFILE=
20-
- LLVM_VERSION="3.9.0" BINDGEN_JOB="integration" BINDGEN_PROFILE="--release"
21-
- LLVM_VERSION="4.0.0" BINDGEN_JOB="test" BINDGEN_PROFILE=
22-
- LLVM_VERSION="4.0.0" BINDGEN_JOB="test" BINDGEN_PROFILE="--release"
23-
- LLVM_VERSION="4.0.0" BINDGEN_JOB="test" BINDGEN_PROFILE= BINDGEN_FEATURES="testing_only_extra_assertions"
24-
- LLVM_VERSION="4.0.0" BINDGEN_JOB="test" BINDGEN_PROFILE="--release" BINDGEN_FEATURES="testing_only_extra_assertions"
25-
- LLVM_VERSION="4.0.0" BINDGEN_JOB="integration" BINDGEN_PROFILE=
26-
- LLVM_VERSION="4.0.0" BINDGEN_JOB="integration" BINDGEN_PROFILE="--release"
27-
- LLVM_VERSION="4.0.0" BINDGEN_JOB="expectations" BINDGEN_PROFILE=
28-
- LLVM_VERSION="4.0.0" BINDGEN_JOB="expectations" BINDGEN_PROFILE="--release"
29-
- LLVM_VERSION="4.0.0" BINDGEN_JOB="misc"
30-
- LLVM_VERSION="4.0.0" BINDGEN_JOB="quickchecking"
13+
- LLVM_VERSION="3.8" BINDGEN_JOB="test" BINDGEN_PROFILE=
14+
- LLVM_VERSION="3.8" BINDGEN_JOB="test" BINDGEN_PROFILE="--release"
15+
- LLVM_VERSION="3.8" BINDGEN_JOB="integration" BINDGEN_PROFILE=
16+
- LLVM_VERSION="3.8" BINDGEN_JOB="integration" BINDGEN_PROFILE="--release"
17+
- LLVM_VERSION="3.9" BINDGEN_JOB="test" BINDGEN_PROFILE=
18+
- LLVM_VERSION="3.9" BINDGEN_JOB="test" BINDGEN_PROFILE="--release"
19+
- LLVM_VERSION="3.9" BINDGEN_JOB="integration" BINDGEN_PROFILE=
20+
- LLVM_VERSION="3.9" BINDGEN_JOB="integration" BINDGEN_PROFILE="--release"
21+
- LLVM_VERSION="4.0" BINDGEN_JOB="test" BINDGEN_PROFILE=
22+
- LLVM_VERSION="4.0" BINDGEN_JOB="test" BINDGEN_PROFILE="--release"
23+
- LLVM_VERSION="4.0" BINDGEN_JOB="integration" BINDGEN_PROFILE=
24+
- LLVM_VERSION="4.0" BINDGEN_JOB="integration" BINDGEN_PROFILE="--release"
25+
- LLVM_VERSION="5.0" BINDGEN_JOB="test" BINDGEN_PROFILE=
26+
- LLVM_VERSION="5.0" BINDGEN_JOB="test" BINDGEN_PROFILE="--release"
27+
- LLVM_VERSION="5.0" BINDGEN_JOB="test" BINDGEN_PROFILE= BINDGEN_FEATURES="testing_only_extra_assertions"
28+
- LLVM_VERSION="5.0" BINDGEN_JOB="test" BINDGEN_PROFILE="--release" BINDGEN_FEATURES="testing_only_extra_assertions"
29+
- LLVM_VERSION="5.0" BINDGEN_JOB="integration" BINDGEN_PROFILE=
30+
- LLVM_VERSION="5.0" BINDGEN_JOB="integration" BINDGEN_PROFILE="--release"
31+
- LLVM_VERSION="5.0" BINDGEN_JOB="expectations" BINDGEN_PROFILE=
32+
- LLVM_VERSION="5.0" BINDGEN_JOB="expectations" BINDGEN_PROFILE="--release"
33+
- LLVM_VERSION="5.0" BINDGEN_JOB="misc"
34+
- LLVM_VERSION="5.0" BINDGEN_JOB="quickchecking"
3135

3236
matrix:
3337
fast_finish: true
3438
allow_failures:
35-
- env: LLVM_VERSION=4.0.0 BINDGEN_JOB=rustfmt
39+
- env: LLVM_VERSION=5.0 BINDGEN_JOB=rustfmt
3640

3741
cache:
3842
directories:

Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ cexpr = "0.2"
4747
cfg-if = "0.1.0"
4848
# This kinda sucks: https://github.com/rust-lang/cargo/issues/1982
4949
clap = "2"
50-
clang-sys = { version = "0.22.0", features = ["runtime", "clang_3_9"] }
50+
clang-sys = { version = "0.22.0", features = ["runtime", "clang_6_0"] }
5151
lazy_static = "1"
5252
peeking_take_while = "0.1.2"
5353
quote = "0.3.15"
@@ -71,6 +71,7 @@ static = []
7171
# on bindgen!
7272
testing_only_docs = []
7373
testing_only_extra_assertions = []
74+
testing_only_libclang_5 = []
7475
testing_only_libclang_4 = []
7576
testing_only_libclang_3_9 = []
7677
testing_only_libclang_3_8 = []

appveyor.yml

+6
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,18 @@ environment:
88
- TARGET: gnu
99
LLVM_VERSION: 4.0.0-1
1010
BINDGEN_FEATURES: testing_only_libclang_4
11+
- TARGET: msvc
12+
LLVM_VERSION: 5.0.0-1
13+
BINDGEN_FEATURES: testing_only_libclang_5
1114
- TARGET: msvc
1215
LLVM_VERSION: 3.9.0
1316
BINDGEN_FEATURES: testing_only_libclang_3_9
1417
- TARGET: msvc
1518
LLVM_VERSION: 4.0.0
1619
BINDGEN_FEATURES: testing_only_libclang_4
20+
- TARGET: msvc
21+
LLVM_VERSION: 5.0.0
22+
BINDGEN_FEATURES: testing_only_libclang_5
1723

1824
configuration:
1925
- stable

bindgen-integration/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ bindgen = { path = ".." }
1111
gcc = "0.3"
1212

1313
[features]
14+
testing_only_libclang_5 = ["bindgen/testing_only_libclang_5"]
1415
testing_only_libclang_4 = ["bindgen/testing_only_libclang_4"]
1516
testing_only_libclang_3_9 = ["bindgen/testing_only_libclang_3_9"]
1617
testing_only_libclang_3_8 = ["bindgen/testing_only_libclang_3_8"]

ci/before_install.sh

+40-16
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,55 @@ if [ "${TRAVIS_OS_NAME}" == "osx" ]; then
66
rvm get head || true
77
fi
88

9-
function llvm_download_if_needed() {
10-
export LLVM_VERSION_TRIPLE="${LLVM_VERSION}"
11-
export LLVM=clang+llvm-${LLVM_VERSION_TRIPLE}-x86_64-$1
12-
13-
local llvm_build_dir="$HOME/.llvm-builds/${LLVM}"
14-
15-
if [ -d "${llvm_build_dir}" ]; then
16-
echo "Using cached LLVM build for ${LLVM} in ${llvm_build_dir}";
9+
function llvm_linux_target_triple() {
10+
if [ "$1" == "5.0" ]; then
11+
echo "linux-x86_64-ubuntu14.04"
1712
else
18-
wget http://llvm.org/releases/${LLVM_VERSION_TRIPLE}/${LLVM}.tar.xz
19-
mkdir -p "${llvm_build_dir}"
20-
tar -xf ${LLVM}.tar.xz -C "${llvm_build_dir}" --strip-components=1
13+
echo "x86_64-linux-gnu-ubuntu-14.04"
2114
fi
15+
}
2216

23-
export LLVM_CONFIG_PATH="${llvm_build_dir}/bin/llvm-config"
24-
if [ "${TRAVIS_OS_NAME}" == "osx" ]; then
25-
cp "${llvm_build_dir}/lib/libclang.dylib" /usr/local/lib/libclang.dylib
17+
function llvm_version_triple() {
18+
if [ "$1" == "3.5" ]; then
19+
echo "3.5.2"
20+
elif [ "$1" == "3.6" ]; then
21+
echo "3.6.2"
22+
elif [ "$1" == "3.7" ]; then
23+
echo "3.7.1"
24+
elif [ "$1" == "3.8" ]; then
25+
echo "3.8.1"
26+
elif [ "$1" == "3.9" ]; then
27+
echo "3.9.0"
28+
elif [ "$1" == "4.0" ]; then
29+
echo "4.0.0"
30+
elif [ "$1" == "5.0" ]; then
31+
echo "5.0.0"
2632
fi
2733
}
2834

35+
function llvm_download() {
36+
export LLVM_VERSION_TRIPLE=`llvm_version_triple ${LLVM_VERSION}`
37+
export LLVM=clang+llvm-${LLVM_VERSION_TRIPLE}-$1
38+
export LLVM_DIRECTORY="$HOME/.llvm/${LLVM}"
39+
40+
if [ -d "${LLVM_DIRECTORY}" ]; then
41+
echo "Using cached LLVM download for ${LLVM}..."
42+
else
43+
wget http://releases.llvm.org/${LLVM_VERSION_TRIPLE}/${LLVM}.tar.xz
44+
mkdir -p "${LLVM_DIRECTORY}"
45+
tar xf ${LLVM}.tar.xz -C "${LLVM_DIRECTORY}" --strip-components=1
46+
fi
47+
48+
export LLVM_CONFIG_PATH="${LLVM_DIRECTORY}/bin/llvm-config"
49+
}
2950

3051
if [ "${TRAVIS_OS_NAME}" == "linux" ]; then
31-
llvm_download_if_needed linux-gnu-ubuntu-14.04
52+
llvm_download `llvm_linux_target_triple ${LLVM_VERSION}`
53+
export LD_LIBRARY_PATH="${LLVM_DIRECTORY}/lib":$LD_LIBRARY_PATH
3254
else
33-
llvm_download_if_needed apple-darwin
55+
llvm_download x86_64-apple-darwin
56+
cp "${LLVM_DIRECTORY}/lib/libclang.dylib" /usr/local/lib/libclang.dylib
57+
export DYLD_LIBRARY_PATH="${LLVM_DIRECTORY}/lib":$DYLD_LIBRARY_PATH
3458
fi
3559

3660
popd

src/clang.rs

+32
Original file line numberDiff line numberDiff line change
@@ -1812,3 +1812,35 @@ impl Drop for EvalResult {
18121812
unsafe { clang_EvalResult_dispose(self.x) };
18131813
}
18141814
}
1815+
1816+
/// Target information obtained from libclang.
1817+
#[derive(Debug)]
1818+
pub struct TargetInfo {
1819+
/// The target triple.
1820+
pub triple: String,
1821+
/// The width of the pointer _in bits_.
1822+
pub pointer_width: usize,
1823+
}
1824+
1825+
impl TargetInfo {
1826+
/// Tries to obtain target information from libclang.
1827+
pub fn new(tu: &TranslationUnit) -> Option<Self> {
1828+
if !clang_getTranslationUnitTargetInfo::is_loaded() {
1829+
return None;
1830+
}
1831+
let triple;
1832+
let pointer_width;
1833+
unsafe {
1834+
let ti = clang_getTranslationUnitTargetInfo(tu.x);
1835+
triple = cxstring_into_string(clang_TargetInfo_getTriple(ti));
1836+
pointer_width = clang_TargetInfo_getPointerWidth(ti);
1837+
clang_TargetInfo_dispose(ti);
1838+
}
1839+
assert!(pointer_width > 0);
1840+
assert_eq!(pointer_width % 8, 0);
1841+
Some(TargetInfo {
1842+
triple,
1843+
pointer_width: pointer_width as usize,
1844+
})
1845+
}
1846+
}

src/codegen/mod.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ use std::collections::{HashSet, VecDeque};
4545
use std::collections::hash_map::{Entry, HashMap};
4646
use std::fmt::Write;
4747
use std::iter;
48-
use std::mem;
4948
use std::ops;
5049

5150
// Name of type defined in constified enum module
@@ -1777,8 +1776,9 @@ impl CodeGenerator for CompInfo {
17771776
let align = layout.align;
17781777

17791778
let check_struct_align =
1780-
if align > mem::size_of::<*mut ()>() {
1781-
// FIXME when [RFC 1358](https://github.com/rust-lang/rust/issues/33626) ready
1779+
if align > ctx.target_pointer_size() &&
1780+
!ctx.options().rust_features().repr_align
1781+
{
17821782
None
17831783
} else {
17841784
Some(quote! {
@@ -2720,9 +2720,8 @@ trait TryToOpaque {
27202720
/// leverage the blanket impl for this trait.
27212721
trait ToOpaque: TryToOpaque {
27222722
fn get_layout(&self, ctx: &BindgenContext, extra: &Self::Extra) -> Layout {
2723-
self.try_get_layout(ctx, extra).unwrap_or_else(
2724-
|_| Layout::for_size(1),
2725-
)
2723+
self.try_get_layout(ctx, extra)
2724+
.unwrap_or_else(|_| Layout::for_size(ctx, 1))
27262725
}
27272726

27282727
fn to_opaque(

src/codegen/struct_layout.rs

+25-18
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use ir::layout::Layout;
88
use ir::ty::{Type, TypeKind};
99
use quote;
1010
use std::cmp;
11-
use std::mem;
1211

1312
/// Trace the layout of struct.
1413
#[derive(Debug)]
@@ -101,7 +100,7 @@ impl<'a> StructLayoutTracker<'a> {
101100
pub fn saw_vtable(&mut self) {
102101
debug!("saw vtable for {}", self.name);
103102

104-
let ptr_size = mem::size_of::<*mut ()>();
103+
let ptr_size = self.ctx.target_pointer_size();
105104
self.latest_offset += ptr_size;
106105
self.latest_field_layout = Some(Layout::new(ptr_size, ptr_size));
107106
self.max_field_align = ptr_size;
@@ -165,15 +164,13 @@ impl<'a> StructLayoutTracker<'a> {
165164
// can support.
166165
//
167166
// This means that the structs in the array are super-unsafe to
168-
// access, since they won't be properly aligned, but *shrug*.
169-
if let Some(layout) = self.ctx.resolve_type(inner).layout(
170-
self.ctx,
171-
)
172-
{
173-
if layout.align > mem::size_of::<*mut ()>() {
174-
field_layout.size = align_to(layout.size, layout.align) *
175-
len;
176-
field_layout.align = mem::size_of::<*mut ()>();
167+
// access, since they won't be properly aligned, but there's not too
168+
// much we can do about it.
169+
if let Some(layout) = self.ctx.resolve_type(inner).layout(self.ctx) {
170+
if layout.align > self.ctx.target_pointer_size() {
171+
field_layout.size =
172+
align_to(layout.size, layout.align) * len;
173+
field_layout.align = self.ctx.target_pointer_size();
177174
}
178175
}
179176
}
@@ -193,7 +190,7 @@ impl<'a> StructLayoutTracker<'a> {
193190

194191
// Otherwise the padding is useless.
195192
let need_padding = padding_bytes >= field_layout.align ||
196-
field_layout.align > mem::size_of::<*mut ()>();
193+
field_layout.align > self.ctx.target_pointer_size();
197194

198195
self.latest_offset += padding_bytes;
199196

@@ -215,7 +212,7 @@ impl<'a> StructLayoutTracker<'a> {
215212
if need_padding && padding_bytes != 0 {
216213
Some(Layout::new(
217214
padding_bytes,
218-
cmp::min(field_layout.align, mem::size_of::<*mut ()>()),
215+
cmp::min(field_layout.align, self.ctx.target_pointer_size())
219216
))
220217
} else {
221218
None
@@ -267,15 +264,15 @@ impl<'a> StructLayoutTracker<'a> {
267264
(self.last_field_was_bitfield &&
268265
padding_bytes >=
269266
self.latest_field_layout.unwrap().align) ||
270-
layout.align > mem::size_of::<*mut ()>())
267+
layout.align > self.ctx.target_pointer_size())
271268
{
272269
let layout = if self.is_packed {
273270
Layout::new(padding_bytes, 1)
274271
} else if self.last_field_was_bitfield ||
275-
layout.align > mem::size_of::<*mut ()>()
272+
layout.align > self.ctx.target_pointer_size()
276273
{
277274
// We've already given up on alignment here.
278-
Layout::for_size(padding_bytes)
275+
Layout::for_size(self.ctx, padding_bytes)
279276
} else {
280277
Layout::new(padding_bytes, layout.align)
281278
};
@@ -289,8 +286,18 @@ impl<'a> StructLayoutTracker<'a> {
289286
}
290287

291288
pub fn requires_explicit_align(&self, layout: Layout) -> bool {
292-
self.max_field_align < layout.align &&
293-
layout.align <= mem::size_of::<*mut ()>()
289+
if self.max_field_align >= layout.align {
290+
return false;
291+
}
292+
// At this point we require explicit alignment, but we may not be able
293+
// to generate the right bits, let's double check.
294+
if self.ctx.options().rust_features().repr_align {
295+
return true;
296+
}
297+
298+
// We can only generate up-to a word of alignment unless we support
299+
// repr(align).
300+
layout.align <= self.ctx.target_pointer_size()
294301
}
295302

296303
fn padding_bytes(&self, layout: Layout) -> usize {

0 commit comments

Comments
 (0)