Skip to content

Commit cd8aacc

Browse files
committed
trans: Upgrade LLVM
This brings some routine upgrades to the bundled LLVM that we're using, the most notable of which is a bug fix to the way we handle range asserts when loading the discriminant of an enum. This fix ended up being very similar to f9d4149 where we basically can't have a range assert when loading a discriminant due to filling drop, and appropriate flags were added to communicate this to `trans::adt`.
1 parent 142214d commit cd8aacc

File tree

17 files changed

+124
-44
lines changed

17 files changed

+124
-44
lines changed

src/librustc_llvm/archive_ro.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,14 @@ impl Drop for ArchiveRO {
7979
}
8080

8181
impl<'a> Iterator for Iter<'a> {
82-
type Item = Child<'a>;
82+
type Item = Result<Child<'a>, String>;
8383

84-
fn next(&mut self) -> Option<Child<'a>> {
84+
fn next(&mut self) -> Option<Result<Child<'a>, String>> {
8585
let ptr = unsafe { ::LLVMRustArchiveIteratorNext(self.ptr) };
8686
if ptr.is_null() {
87-
None
87+
::last_error().map(Err)
8888
} else {
89-
Some(Child { ptr: ptr, _data: marker::PhantomData })
89+
Some(Ok(Child { ptr: ptr, _data: marker::PhantomData }))
9090
}
9191
}
9292
}

src/librustc_llvm/lib.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ pub use self::DiagnosticSeverity::*;
5656
pub use self::Linkage::*;
5757
pub use self::DLLStorageClassTypes::*;
5858

59-
use std::ffi::CString;
59+
use std::ffi::{CString, CStr};
6060
use std::cell::RefCell;
6161
use std::slice;
6262
use libc::{c_uint, c_ushort, uint64_t, c_int, size_t, c_char};
@@ -2404,6 +2404,20 @@ pub fn initialize_available_targets() {
24042404
init_pnacl();
24052405
}
24062406

2407+
pub fn last_error() -> Option<String> {
2408+
unsafe {
2409+
let cstr = LLVMRustGetLastError();
2410+
if cstr.is_null() {
2411+
None
2412+
} else {
2413+
let err = CStr::from_ptr(cstr).to_bytes();
2414+
let err = String::from_utf8_lossy(err).to_string();
2415+
libc::free(cstr as *mut _);
2416+
Some(err)
2417+
}
2418+
}
2419+
}
2420+
24072421
// The module containing the native LLVM dependencies, generated by the build system
24082422
// Note that this must come after the rustllvm extern declaration so that
24092423
// parts of LLVM that rustllvm depends on aren't thrown away by the linker.

src/librustc_metadata/loader.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -729,7 +729,7 @@ pub fn note_crate_name(err: &mut DiagnosticBuilder, name: &str) {
729729
impl ArchiveMetadata {
730730
fn new(ar: ArchiveRO) -> Option<ArchiveMetadata> {
731731
let data = {
732-
let section = ar.iter().find(|sect| {
732+
let section = ar.iter().filter_map(|s| s.ok()).find(|sect| {
733733
sect.name() == Some(METADATA_FILENAME)
734734
});
735735
match section {

src/librustc_trans/back/archive.rs

+32-5
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ impl<'a> ArchiveBuilder<'a> {
124124
}
125125
let archive = self.src_archive.as_ref().unwrap().as_ref().unwrap();
126126
let ret = archive.iter()
127+
.filter_map(|child| child.ok())
127128
.filter(is_relevant_child)
128129
.filter_map(|child| child.name())
129130
.filter(|name| !self.removals.iter().any(|x| x == name))
@@ -332,9 +333,15 @@ impl<'a> ArchiveBuilder<'a> {
332333
// We skip any files explicitly desired for skipping, and we also skip
333334
// all SYMDEF files as these are just magical placeholders which get
334335
// re-created when we make a new archive anyway.
335-
for file in archive.iter().filter(is_relevant_child) {
336+
for file in archive.iter() {
337+
let file = try!(file.map_err(string2io));
338+
if !is_relevant_child(&file) {
339+
continue
340+
}
336341
let filename = file.name().unwrap();
337-
if skip(filename) { continue }
342+
if skip(filename) {
343+
continue
344+
}
338345
let filename = Path::new(filename).file_name().unwrap()
339346
.to_str().unwrap();
340347

@@ -448,6 +455,7 @@ impl<'a> ArchiveBuilder<'a> {
448455
unsafe {
449456
if let Some(archive) = self.src_archive() {
450457
for child in archive.iter() {
458+
let child = try!(child.map_err(string2io));
451459
let child_name = match child.name() {
452460
Some(s) => s,
453461
None => continue,
@@ -475,10 +483,25 @@ impl<'a> ArchiveBuilder<'a> {
475483
strings.push(name);
476484
}
477485
Addition::Archive { archive, archive_name: _, mut skip } => {
478-
for child in archive.iter().filter(is_relevant_child) {
486+
for child in archive.iter() {
487+
let child = try!(child.map_err(string2io));
488+
if !is_relevant_child(&child) {
489+
continue
490+
}
479491
let child_name = child.name().unwrap();
480-
if skip(child_name) { continue }
481-
492+
if skip(child_name) {
493+
continue
494+
}
495+
496+
// It appears that LLVM's archive writer is a little
497+
// buggy if the name we pass down isn't just the
498+
// filename component, so chop that off here and
499+
// pass it in.
500+
//
501+
// See LLVM bug 25877 for more info.
502+
let child_name = Path::new(child_name)
503+
.file_name().unwrap()
504+
.to_str().unwrap();
482505
let name = try!(CString::new(child_name));
483506
let m = llvm::LLVMRustArchiveMemberNew(ptr::null(),
484507
name.as_ptr(),
@@ -517,3 +540,7 @@ impl<'a> ArchiveBuilder<'a> {
517540
}
518541
}
519542
}
543+
544+
fn string2io(s: String) -> io::Error {
545+
io::Error::new(io::ErrorKind::Other, format!("bad archive: {}", s))
546+
}

src/librustc_trans/back/lto.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
5252
link::each_linked_rlib(sess, &mut |_, path| {
5353
let archive = ArchiveRO::open(&path).expect("wanted an rlib");
5454
let bytecodes = archive.iter().filter_map(|child| {
55-
child.name().map(|name| (name, child))
55+
child.ok().and_then(|c| c.name().map(|name| (name, c)))
5656
}).filter(|&(name, _)| name.ends_with("bytecode.deflate"));
5757
for (name, data) in bytecodes {
5858
let bc_encoded = data.data();

src/librustc_trans/back/write.rs

+4-12
Original file line numberDiff line numberDiff line change
@@ -27,24 +27,16 @@ use std::collections::HashMap;
2727
use std::ffi::{CStr, CString};
2828
use std::fs;
2929
use std::path::{Path, PathBuf};
30-
use std::ptr;
3130
use std::str;
3231
use std::sync::{Arc, Mutex};
3332
use std::sync::mpsc::channel;
3433
use std::thread;
35-
use libc::{self, c_uint, c_int, c_void};
34+
use libc::{c_uint, c_int, c_void};
3635

3736
pub fn llvm_err(handler: &errors::Handler, msg: String) -> ! {
38-
unsafe {
39-
let cstr = llvm::LLVMRustGetLastError();
40-
if cstr == ptr::null() {
41-
panic!(handler.fatal(&msg[..]));
42-
} else {
43-
let err = CStr::from_ptr(cstr).to_bytes();
44-
let err = String::from_utf8_lossy(err).to_string();
45-
libc::free(cstr as *mut _);
46-
panic!(handler.fatal(&format!("{}: {}", &msg[..], &err[..])));
47-
}
37+
match llvm::last_error() {
38+
Some(err) => panic!(handler.fatal(&format!("{}: {}", msg, err))),
39+
None => panic!(handler.fatal(&msg)),
4840
}
4941
}
5042

src/librustc_trans/trans/_match.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1271,7 +1271,8 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
12711271
};
12721272
}
12731273
Variant(_, ref repr, _, _) => {
1274-
let (the_kind, val_opt) = adt::trans_switch(bcx, &**repr, val.val);
1274+
let (the_kind, val_opt) = adt::trans_switch(bcx, &repr,
1275+
val.val, true);
12751276
kind = the_kind;
12761277
if let Some(tval) = val_opt { test_val = tval; }
12771278
}

src/librustc_trans/trans/adt.rs

+20-8
Original file line numberDiff line numberDiff line change
@@ -890,12 +890,15 @@ fn struct_llfields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, st: &Struct<'tcx>,
890890
///
891891
/// This should ideally be less tightly tied to `_match`.
892892
pub fn trans_switch<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
893-
r: &Repr<'tcx>, scrutinee: ValueRef)
893+
r: &Repr<'tcx>,
894+
scrutinee: ValueRef,
895+
range_assert: bool)
894896
-> (_match::BranchKind, Option<ValueRef>) {
895897
match *r {
896898
CEnum(..) | General(..) |
897899
RawNullablePointer { .. } | StructWrappedNullablePointer { .. } => {
898-
(_match::Switch, Some(trans_get_discr(bcx, r, scrutinee, None)))
900+
(_match::Switch, Some(trans_get_discr(bcx, r, scrutinee, None,
901+
range_assert)))
899902
}
900903
Univariant(..) => {
901904
// N.B.: Univariant means <= 1 enum variants (*not* == 1 variants).
@@ -916,14 +919,18 @@ pub fn is_discr_signed<'tcx>(r: &Repr<'tcx>) -> bool {
916919

917920
/// Obtain the actual discriminant of a value.
918921
pub fn trans_get_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
919-
scrutinee: ValueRef, cast_to: Option<Type>)
922+
scrutinee: ValueRef, cast_to: Option<Type>,
923+
range_assert: bool)
920924
-> ValueRef {
921925
debug!("trans_get_discr r: {:?}", r);
922926
let val = match *r {
923-
CEnum(ity, min, max) => load_discr(bcx, ity, scrutinee, min, max),
927+
CEnum(ity, min, max) => {
928+
load_discr(bcx, ity, scrutinee, min, max, range_assert)
929+
}
924930
General(ity, ref cases, _) => {
925931
let ptr = StructGEP(bcx, scrutinee, 0);
926-
load_discr(bcx, ity, ptr, Disr(0), Disr(cases.len() as u64 - 1))
932+
load_discr(bcx, ity, ptr, Disr(0), Disr(cases.len() as u64 - 1),
933+
range_assert)
927934
}
928935
Univariant(..) => C_u8(bcx.ccx(), 0),
929936
RawNullablePointer { nndiscr, nnty, .. } => {
@@ -950,7 +957,8 @@ fn struct_wrapped_nullable_bitdiscr(bcx: Block, nndiscr: Disr, discrfield: &Disc
950957
}
951958

952959
/// Helper for cases where the discriminant is simply loaded.
953-
fn load_discr(bcx: Block, ity: IntType, ptr: ValueRef, min: Disr, max: Disr)
960+
fn load_discr(bcx: Block, ity: IntType, ptr: ValueRef, min: Disr, max: Disr,
961+
range_assert: bool)
954962
-> ValueRef {
955963
let llty = ll_inttype(bcx.ccx(), ity);
956964
assert_eq!(val_ty(ptr), llty.ptr_to());
@@ -960,7 +968,7 @@ fn load_discr(bcx: Block, ity: IntType, ptr: ValueRef, min: Disr, max: Disr)
960968
let mask = Disr(!0u64 >> (64 - bits));
961969
// For a (max) discr of -1, max will be `-1 as usize`, which overflows.
962970
// However, that is fine here (it would still represent the full range),
963-
if max.wrapping_add(Disr(1)) & mask == min & mask {
971+
if max.wrapping_add(Disr(1)) & mask == min & mask || !range_assert {
964972
// i.e., if the range is everything. The lo==hi case would be
965973
// rejected by the LLVM verifier (it would mean either an
966974
// empty set, which is impossible, or the entire range of the
@@ -1239,10 +1247,14 @@ pub fn fold_variants<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
12391247
// runtime, so the basic block isn't actually unreachable, so we
12401248
// need to make it do something with defined behavior. In this case
12411249
// we just return early from the function.
1250+
//
1251+
// Note that this is also why the `trans_get_discr` below has
1252+
// `false` to indicate that loading the discriminant should
1253+
// not have a range assert.
12421254
let ret_void_cx = fcx.new_temp_block("enum-variant-iter-ret-void");
12431255
RetVoid(ret_void_cx, DebugLoc::None);
12441256

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

src/librustc_trans/trans/base.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,7 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
556556
// NB: we must hit the discriminant first so that structural
557557
// comparison know not to proceed when the discriminants differ.
558558

559-
match adt::trans_switch(cx, &*repr, av) {
559+
match adt::trans_switch(cx, &*repr, av, false) {
560560
(_match::Single, None) => {
561561
if n_variants != 0 {
562562
assert!(n_variants == 1);

src/librustc_trans/trans/expr.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2116,7 +2116,8 @@ fn trans_imm_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
21162116
let datum = unpack_datum!(
21172117
bcx, datum.to_lvalue_datum(bcx, "trans_imm_cast", expr.id));
21182118
let llexpr_ptr = datum.to_llref();
2119-
let discr = adt::trans_get_discr(bcx, &*repr, llexpr_ptr, Some(Type::i64(ccx)));
2119+
let discr = adt::trans_get_discr(bcx, &*repr, llexpr_ptr,
2120+
Some(Type::i64(ccx)), true);
21202121
ll_t_in = val_ty(discr);
21212122
(discr, adt::is_discr_signed(&*repr))
21222123
} else {

src/librustc_trans/trans/intrinsic.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -655,7 +655,8 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
655655
match val_ty.sty {
656656
ty::TyEnum(..) => {
657657
let repr = adt::represent_type(ccx, *val_ty);
658-
adt::trans_get_discr(bcx, &*repr, llargs[0], Some(llret_ty))
658+
adt::trans_get_discr(bcx, &*repr, llargs[0],
659+
Some(llret_ty), true)
659660
}
660661
_ => C_null(llret_ty)
661662
}

src/librustc_trans/trans/mir/block.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
5555
let discr_lvalue = self.trans_lvalue(bcx, discr);
5656
let ty = discr_lvalue.ty.to_ty(bcx.tcx());
5757
let repr = adt::represent_type(bcx.ccx(), ty);
58-
let discr = adt::trans_get_discr(bcx, &repr, discr_lvalue.llval, None);
58+
let discr = adt::trans_get_discr(bcx, &repr, discr_lvalue.llval,
59+
None, true);
5960

6061
// The else branch of the Switch can't be hit, so branch to an unreachable
6162
// instruction so LLVM knows that

src/llvm

Submodule llvm updated 6395 files

src/rustllvm/ArchiveWrapper.cpp

+19-3
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,13 @@ struct LLVMRustArchiveMember {
2424
const char *name;
2525
Archive::Child child;
2626

27-
LLVMRustArchiveMember(): filename(NULL), name(NULL), child(NULL, NULL) {}
27+
LLVMRustArchiveMember(): filename(NULL), name(NULL),
28+
#if LLVM_VERSION_MINOR >= 8
29+
child(NULL, NULL, NULL)
30+
#else
31+
child(NULL, NULL)
32+
#endif
33+
{}
2834
~LLVMRustArchiveMember() {}
2935
};
3036

@@ -92,8 +98,18 @@ extern "C" const Archive::Child*
9298
LLVMRustArchiveIteratorNext(RustArchiveIterator *rai) {
9399
if (rai->cur == rai->end)
94100
return NULL;
95-
const Archive::Child *cur = rai->cur.operator->();
96-
Archive::Child *ret = new Archive::Child(*cur);
101+
#if LLVM_VERSION_MINOR >= 8
102+
const ErrorOr<Archive::Child>* cur = rai->cur.operator->();
103+
if (!*cur) {
104+
LLVMRustSetLastError(cur->getError().message().c_str());
105+
return NULL;
106+
}
107+
const Archive::Child &child = cur->get();
108+
#else
109+
const Archive::Child &child = *rai->cur.operator->();
110+
#endif
111+
Archive::Child *ret = new Archive::Child(child);
112+
97113
++rai->cur;
98114
return ret;
99115
}

src/rustllvm/RustWrapper.cpp

+17-1
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,19 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateFunction(
348348
LLVMValueRef Fn,
349349
LLVMMetadataRef TParam,
350350
LLVMMetadataRef Decl) {
351+
#if LLVM_VERSION_MINOR >= 8
352+
DITemplateParameterArray TParams =
353+
DITemplateParameterArray(unwrap<MDTuple>(TParam));
354+
DISubprogram *Sub = Builder->createFunction(
355+
unwrapDI<DIScope>(Scope), Name, LinkageName,
356+
unwrapDI<DIFile>(File), LineNo,
357+
unwrapDI<DISubroutineType>(Ty), isLocalToUnit, isDefinition, ScopeLine,
358+
Flags, isOptimized,
359+
TParams,
360+
unwrapDIptr<DISubprogram>(Decl));
361+
unwrap<Function>(Fn)->setSubprogram(Sub);
362+
return wrap(Sub);
363+
#else
351364
return wrap(Builder->createFunction(
352365
unwrapDI<DIScope>(Scope), Name, LinkageName,
353366
unwrapDI<DIFile>(File), LineNo,
@@ -356,6 +369,7 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateFunction(
356369
unwrap<Function>(Fn),
357370
unwrapDIptr<MDNode>(TParam),
358371
unwrapDIptr<MDNode>(Decl)));
372+
#endif
359373
}
360374

361375
extern "C" LLVMMetadataRef LLVMDIBuilderCreateBasicType(
@@ -830,7 +844,9 @@ LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) {
830844
#if LLVM_VERSION_MINOR >= 6
831845
raw_string_ostream Stream(Err);
832846
DiagnosticPrinterRawOStream DP(Stream);
833-
#if LLVM_VERSION_MINOR >= 7
847+
#if LLVM_VERSION_MINOR >= 8
848+
if (Linker::linkModules(*Dst, std::move(Src.get()))) {
849+
#elif LLVM_VERSION_MINOR >= 7
834850
if (Linker::LinkModules(Dst, Src->get(), [&](const DiagnosticInfo &DI) { DI.print(DP); })) {
835851
#else
836852
if (Linker::LinkModules(Dst, *Src, [&](const DiagnosticInfo &DI) { DI.print(DP); })) {

src/rustllvm/llvm-auto-clean-trigger

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# If this file is modified, then llvm will be forcibly cleaned and then rebuilt.
22
# The actual contents of this file do not matter, but to trigger a change on the
33
# build bots then the contents should be changed so git updates the mtime.
4-
2015-12-02
4+
2015-01-27

src/test/run-make/target-specs/my-awesome-platform.json

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
{
2-
"data-layout": "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32",
32
"llvm-target": "i686-unknown-linux-gnu",
43
"target-endian": "little",
54
"target-pointer-width": "32",

0 commit comments

Comments
 (0)