Skip to content

Commit a6612ce

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 2343a92 commit a6612ce

File tree

16 files changed

+123
-43
lines changed

16 files changed

+123
-43
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
@@ -55,7 +55,7 @@ pub use self::DiagnosticSeverity::*;
5555
pub use self::Linkage::*;
5656
pub use self::DLLStorageClassTypes::*;
5757

58-
use std::ffi::CString;
58+
use std::ffi::{CString, CStr};
5959
use std::cell::RefCell;
6060
use std::slice;
6161
use libc::{c_uint, c_ushort, uint64_t, c_int, size_t, c_char};
@@ -2390,6 +2390,20 @@ pub fn initialize_available_targets() {
23902390
init_pnacl();
23912391
}
23922392

2393+
pub fn last_error() -> Option<String> {
2394+
unsafe {
2395+
let cstr = LLVMRustGetLastError();
2396+
if cstr.is_null() {
2397+
None
2398+
} else {
2399+
let err = CStr::from_ptr(cstr).to_bytes();
2400+
let err = String::from_utf8_lossy(err).to_string();
2401+
libc::free(cstr as *mut _);
2402+
Some(err)
2403+
}
2404+
}
2405+
}
2406+
23932407
// The module containing the native LLVM dependencies, generated by the build system
23942408
// Note that this must come after the rustllvm extern declaration so that
23952409
// 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
@@ -704,7 +704,7 @@ pub fn note_crate_name(diag: &Handler, name: &str) {
704704
impl ArchiveMetadata {
705705
fn new(ar: ArchiveRO) -> Option<ArchiveMetadata> {
706706
let data = {
707-
let section = ar.iter().find(|sect| {
707+
let section = ar.iter().filter_map(|s| s.ok()).find(|sect| {
708708
sect.name() == Some(METADATA_FILENAME)
709709
});
710710
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

@@ -447,6 +454,7 @@ impl<'a> ArchiveBuilder<'a> {
447454
unsafe {
448455
if let Some(archive) = self.src_archive() {
449456
for child in archive.iter() {
457+
let child = try!(child.map_err(string2io));
450458
let child_name = match child.name() {
451459
Some(s) => s,
452460
None => continue,
@@ -474,10 +482,25 @@ impl<'a> ArchiveBuilder<'a> {
474482
strings.push(name);
475483
}
476484
Addition::Archive { archive, archive_name: _, mut skip } => {
477-
for child in archive.iter().filter(is_relevant_child) {
485+
for child in archive.iter() {
486+
let child = try!(child.map_err(string2io));
487+
if !is_relevant_child(&child) {
488+
continue
489+
}
478490
let child_name = child.name().unwrap();
479-
if skip(child_name) { continue }
480-
491+
if skip(child_name) {
492+
continue
493+
}
494+
495+
// It appears that LLVM's archive writer is a little
496+
// buggy if the name we pass down isn't just the
497+
// filename component, so chop that off here and
498+
// pass it in.
499+
//
500+
// See LLVM bug 25877 for more info.
501+
let child_name = Path::new(child_name)
502+
.file_name().unwrap()
503+
.to_str().unwrap();
481504
let name = try!(CString::new(child_name));
482505
let m = llvm::LLVMRustArchiveMemberNew(ptr::null(),
483506
name.as_ptr(),
@@ -516,3 +539,7 @@ impl<'a> ArchiveBuilder<'a> {
516539
}
517540
}
518541
}
542+
543+
fn string2io(s: String) -> io::Error {
544+
io::Error::new(io::ErrorKind::Other, format!("bad archive: {}", s))
545+
}

src/librustc_trans/back/lto.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
5151
link::each_linked_rlib(sess, &mut |_, path| {
5252
let archive = ArchiveRO::open(&path).expect("wanted an rlib");
5353
let bytecodes = archive.iter().filter_map(|child| {
54-
child.name().map(|name| (name, child))
54+
child.ok().and_then(|c| c.name().map(|name| (name, c)))
5555
}).filter(|&(name, _)| name.ends_with("bytecode.deflate"));
5656
for (name, data) in bytecodes {
5757
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
@@ -1270,7 +1270,8 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
12701270
};
12711271
}
12721272
Variant(_, ref repr, _, _) => {
1273-
let (the_kind, val_opt) = adt::trans_switch(bcx, &**repr, val.val);
1273+
let (the_kind, val_opt) = adt::trans_switch(bcx, &repr,
1274+
val.val, true);
12741275
kind = the_kind;
12751276
if let Some(tval) = val_opt { test_val = tval; }
12761277
}

src/librustc_trans/trans/adt.rs

+19-8
Original file line numberDiff line numberDiff line change
@@ -889,12 +889,15 @@ fn struct_llfields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, st: &Struct<'tcx>,
889889
///
890890
/// This should ideally be less tightly tied to `_match`.
891891
pub fn trans_switch<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
892-
r: &Repr<'tcx>, scrutinee: ValueRef)
892+
r: &Repr<'tcx>,
893+
scrutinee: ValueRef,
894+
range_assert: bool)
893895
-> (_match::BranchKind, Option<ValueRef>) {
894896
match *r {
895897
CEnum(..) | General(..) |
896898
RawNullablePointer { .. } | StructWrappedNullablePointer { .. } => {
897-
(_match::Switch, Some(trans_get_discr(bcx, r, scrutinee, None)))
899+
(_match::Switch, Some(trans_get_discr(bcx, r, scrutinee, None,
900+
range_assert)))
898901
}
899902
Univariant(..) => {
900903
// N.B.: Univariant means <= 1 enum variants (*not* == 1 variants).
@@ -915,14 +918,17 @@ pub fn is_discr_signed<'tcx>(r: &Repr<'tcx>) -> bool {
915918

916919
/// Obtain the actual discriminant of a value.
917920
pub fn trans_get_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
918-
scrutinee: ValueRef, cast_to: Option<Type>)
921+
scrutinee: ValueRef, cast_to: Option<Type>,
922+
range_assert: bool)
919923
-> ValueRef {
920924
debug!("trans_get_discr r: {:?}", r);
921925
let val = match *r {
922-
CEnum(ity, min, max) => load_discr(bcx, ity, scrutinee, min, max),
926+
CEnum(ity, min, max) => {
927+
load_discr(bcx, ity, scrutinee, min, max, range_assert)
928+
}
923929
General(ity, ref cases, _) => {
924930
let ptr = StructGEP(bcx, scrutinee, 0);
925-
load_discr(bcx, ity, ptr, 0, (cases.len() - 1) as Disr)
931+
load_discr(bcx, ity, ptr, 0, (cases.len() - 1) as Disr, range_assert)
926932
}
927933
Univariant(..) => C_u8(bcx.ccx(), 0),
928934
RawNullablePointer { nndiscr, nnty, .. } => {
@@ -949,7 +955,8 @@ fn struct_wrapped_nullable_bitdiscr(bcx: Block, nndiscr: Disr, discrfield: &Disc
949955
}
950956

951957
/// Helper for cases where the discriminant is simply loaded.
952-
fn load_discr(bcx: Block, ity: IntType, ptr: ValueRef, min: Disr, max: Disr)
958+
fn load_discr(bcx: Block, ity: IntType, ptr: ValueRef, min: Disr, max: Disr,
959+
range_assert: bool)
953960
-> ValueRef {
954961
let llty = ll_inttype(bcx.ccx(), ity);
955962
assert_eq!(val_ty(ptr), llty.ptr_to());
@@ -959,7 +966,7 @@ fn load_discr(bcx: Block, ity: IntType, ptr: ValueRef, min: Disr, max: Disr)
959966
let mask = (!0u64 >> (64 - bits)) as Disr;
960967
// For a (max) discr of -1, max will be `-1 as usize`, which overflows.
961968
// However, that is fine here (it would still represent the full range),
962-
if (max.wrapping_add(1)) & mask == min & mask {
969+
if ((max.wrapping_add(1)) & mask == min & mask) || !range_assert {
963970
// i.e., if the range is everything. The lo==hi case would be
964971
// rejected by the LLVM verifier (it would mean either an
965972
// empty set, which is impossible, or the entire range of the
@@ -1232,10 +1239,14 @@ pub fn fold_variants<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
12321239
// runtime, so the basic block isn't actually unreachable, so we
12331240
// need to make it do something with defined behavior. In this case
12341241
// we just return early from the function.
1242+
//
1243+
// Note that this is also why the `trans_get_discr` below has
1244+
// `false` to indicate that loading the discriminant should
1245+
// not have a range assert.
12351246
let ret_void_cx = fcx.new_temp_block("enum-variant-iter-ret-void");
12361247
RetVoid(ret_void_cx, DebugLoc::None);
12371248

1238-
let discr_val = trans_get_discr(bcx, r, value, None);
1249+
let discr_val = trans_get_discr(bcx, r, value, None, false);
12391250
let llswitch = Switch(bcx, discr_val, ret_void_cx.llbb, cases.len());
12401251
let bcx_next = fcx.new_temp_block("enum-variant-iter-next");
12411252

src/librustc_trans/trans/base.rs

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

555-
match adt::trans_switch(cx, &*repr, av) {
555+
match adt::trans_switch(cx, &*repr, av, false) {
556556
(_match::Single, None) => {
557557
if n_variants != 0 {
558558
assert!(n_variants == 1);

src/librustc_trans/trans/expr.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2111,7 +2111,8 @@ fn trans_imm_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
21112111
let datum = unpack_datum!(
21122112
bcx, datum.to_lvalue_datum(bcx, "trans_imm_cast", expr.id));
21132113
let llexpr_ptr = datum.to_llref();
2114-
let discr = adt::trans_get_discr(bcx, &*repr, llexpr_ptr, Some(Type::i64(ccx)));
2114+
let discr = adt::trans_get_discr(bcx, &*repr, llexpr_ptr,
2115+
Some(Type::i64(ccx)), true);
21152116
ll_t_in = val_ty(discr);
21162117
(discr, adt::is_discr_signed(&*repr))
21172118
} else {

src/librustc_trans/trans/intrinsic.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -652,7 +652,8 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
652652
match val_ty.sty {
653653
ty::TyEnum(..) => {
654654
let repr = adt::represent_type(ccx, *val_ty);
655-
adt::trans_get_discr(bcx, &*repr, llargs[0], Some(llret_ty))
655+
adt::trans_get_discr(bcx, &*repr, llargs[0],
656+
Some(llret_ty), true)
656657
}
657658
_ => C_null(llret_ty)
658659
}

src/librustc_trans/trans/mir/block.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
5656
let represented_ty = adt::represent_type(bcx.ccx(), adt_ty);
5757

5858
let discr_lvalue = self.trans_lvalue(bcx, discr);
59-
let discr = adt::trans_get_discr(bcx, &represented_ty, discr_lvalue.llval, None);
59+
let discr = adt::trans_get_discr(bcx, &represented_ty,
60+
discr_lvalue.llval,
61+
None, true);
6062

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

src/llvm

Submodule llvm updated 6020 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/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)