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 f9d4149c
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`.
This commit is contained in:
parent
142214d1f2
commit
d1cace17af
17 changed files with 123 additions and 43 deletions
|
@ -79,14 +79,14 @@ impl Drop for ArchiveRO {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for Iter<'a> {
|
impl<'a> Iterator for Iter<'a> {
|
||||||
type Item = Child<'a>;
|
type Item = Result<Child<'a>, String>;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Child<'a>> {
|
fn next(&mut self) -> Option<Result<Child<'a>, String>> {
|
||||||
let ptr = unsafe { ::LLVMRustArchiveIteratorNext(self.ptr) };
|
let ptr = unsafe { ::LLVMRustArchiveIteratorNext(self.ptr) };
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
None
|
::last_error().map(Err)
|
||||||
} else {
|
} else {
|
||||||
Some(Child { ptr: ptr, _data: marker::PhantomData })
|
Some(Ok(Child { ptr: ptr, _data: marker::PhantomData }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ pub use self::DiagnosticSeverity::*;
|
||||||
pub use self::Linkage::*;
|
pub use self::Linkage::*;
|
||||||
pub use self::DLLStorageClassTypes::*;
|
pub use self::DLLStorageClassTypes::*;
|
||||||
|
|
||||||
use std::ffi::CString;
|
use std::ffi::{CString, CStr};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
use libc::{c_uint, c_ushort, uint64_t, c_int, size_t, c_char};
|
use libc::{c_uint, c_ushort, uint64_t, c_int, size_t, c_char};
|
||||||
|
@ -2404,6 +2404,20 @@ pub fn initialize_available_targets() {
|
||||||
init_pnacl();
|
init_pnacl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn last_error() -> Option<String> {
|
||||||
|
unsafe {
|
||||||
|
let cstr = LLVMRustGetLastError();
|
||||||
|
if cstr.is_null() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let err = CStr::from_ptr(cstr).to_bytes();
|
||||||
|
let err = String::from_utf8_lossy(err).to_string();
|
||||||
|
libc::free(cstr as *mut _);
|
||||||
|
Some(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// The module containing the native LLVM dependencies, generated by the build system
|
// The module containing the native LLVM dependencies, generated by the build system
|
||||||
// Note that this must come after the rustllvm extern declaration so that
|
// Note that this must come after the rustllvm extern declaration so that
|
||||||
// parts of LLVM that rustllvm depends on aren't thrown away by the linker.
|
// parts of LLVM that rustllvm depends on aren't thrown away by the linker.
|
||||||
|
|
|
@ -729,7 +729,7 @@ pub fn note_crate_name(err: &mut DiagnosticBuilder, name: &str) {
|
||||||
impl ArchiveMetadata {
|
impl ArchiveMetadata {
|
||||||
fn new(ar: ArchiveRO) -> Option<ArchiveMetadata> {
|
fn new(ar: ArchiveRO) -> Option<ArchiveMetadata> {
|
||||||
let data = {
|
let data = {
|
||||||
let section = ar.iter().find(|sect| {
|
let section = ar.iter().filter_map(|s| s.ok()).find(|sect| {
|
||||||
sect.name() == Some(METADATA_FILENAME)
|
sect.name() == Some(METADATA_FILENAME)
|
||||||
});
|
});
|
||||||
match section {
|
match section {
|
||||||
|
|
|
@ -124,6 +124,7 @@ impl<'a> ArchiveBuilder<'a> {
|
||||||
}
|
}
|
||||||
let archive = self.src_archive.as_ref().unwrap().as_ref().unwrap();
|
let archive = self.src_archive.as_ref().unwrap().as_ref().unwrap();
|
||||||
let ret = archive.iter()
|
let ret = archive.iter()
|
||||||
|
.filter_map(|child| child.ok())
|
||||||
.filter(is_relevant_child)
|
.filter(is_relevant_child)
|
||||||
.filter_map(|child| child.name())
|
.filter_map(|child| child.name())
|
||||||
.filter(|name| !self.removals.iter().any(|x| x == name))
|
.filter(|name| !self.removals.iter().any(|x| x == name))
|
||||||
|
@ -332,9 +333,15 @@ impl<'a> ArchiveBuilder<'a> {
|
||||||
// We skip any files explicitly desired for skipping, and we also skip
|
// We skip any files explicitly desired for skipping, and we also skip
|
||||||
// all SYMDEF files as these are just magical placeholders which get
|
// all SYMDEF files as these are just magical placeholders which get
|
||||||
// re-created when we make a new archive anyway.
|
// re-created when we make a new archive anyway.
|
||||||
for file in archive.iter().filter(is_relevant_child) {
|
for file in archive.iter() {
|
||||||
|
let file = try!(file.map_err(string2io));
|
||||||
|
if !is_relevant_child(&file) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
let filename = file.name().unwrap();
|
let filename = file.name().unwrap();
|
||||||
if skip(filename) { continue }
|
if skip(filename) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
let filename = Path::new(filename).file_name().unwrap()
|
let filename = Path::new(filename).file_name().unwrap()
|
||||||
.to_str().unwrap();
|
.to_str().unwrap();
|
||||||
|
|
||||||
|
@ -448,6 +455,7 @@ impl<'a> ArchiveBuilder<'a> {
|
||||||
unsafe {
|
unsafe {
|
||||||
if let Some(archive) = self.src_archive() {
|
if let Some(archive) = self.src_archive() {
|
||||||
for child in archive.iter() {
|
for child in archive.iter() {
|
||||||
|
let child = try!(child.map_err(string2io));
|
||||||
let child_name = match child.name() {
|
let child_name = match child.name() {
|
||||||
Some(s) => s,
|
Some(s) => s,
|
||||||
None => continue,
|
None => continue,
|
||||||
|
@ -475,10 +483,25 @@ impl<'a> ArchiveBuilder<'a> {
|
||||||
strings.push(name);
|
strings.push(name);
|
||||||
}
|
}
|
||||||
Addition::Archive { archive, archive_name: _, mut skip } => {
|
Addition::Archive { archive, archive_name: _, mut skip } => {
|
||||||
for child in archive.iter().filter(is_relevant_child) {
|
for child in archive.iter() {
|
||||||
|
let child = try!(child.map_err(string2io));
|
||||||
|
if !is_relevant_child(&child) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
let child_name = child.name().unwrap();
|
let child_name = child.name().unwrap();
|
||||||
if skip(child_name) { continue }
|
if skip(child_name) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// It appears that LLVM's archive writer is a little
|
||||||
|
// buggy if the name we pass down isn't just the
|
||||||
|
// filename component, so chop that off here and
|
||||||
|
// pass it in.
|
||||||
|
//
|
||||||
|
// See LLVM bug 25877 for more info.
|
||||||
|
let child_name = Path::new(child_name)
|
||||||
|
.file_name().unwrap()
|
||||||
|
.to_str().unwrap();
|
||||||
let name = try!(CString::new(child_name));
|
let name = try!(CString::new(child_name));
|
||||||
let m = llvm::LLVMRustArchiveMemberNew(ptr::null(),
|
let m = llvm::LLVMRustArchiveMemberNew(ptr::null(),
|
||||||
name.as_ptr(),
|
name.as_ptr(),
|
||||||
|
@ -517,3 +540,7 @@ impl<'a> ArchiveBuilder<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn string2io(s: String) -> io::Error {
|
||||||
|
io::Error::new(io::ErrorKind::Other, format!("bad archive: {}", s))
|
||||||
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
|
||||||
link::each_linked_rlib(sess, &mut |_, path| {
|
link::each_linked_rlib(sess, &mut |_, path| {
|
||||||
let archive = ArchiveRO::open(&path).expect("wanted an rlib");
|
let archive = ArchiveRO::open(&path).expect("wanted an rlib");
|
||||||
let bytecodes = archive.iter().filter_map(|child| {
|
let bytecodes = archive.iter().filter_map(|child| {
|
||||||
child.name().map(|name| (name, child))
|
child.ok().and_then(|c| c.name().map(|name| (name, c)))
|
||||||
}).filter(|&(name, _)| name.ends_with("bytecode.deflate"));
|
}).filter(|&(name, _)| name.ends_with("bytecode.deflate"));
|
||||||
for (name, data) in bytecodes {
|
for (name, data) in bytecodes {
|
||||||
let bc_encoded = data.data();
|
let bc_encoded = data.data();
|
||||||
|
|
|
@ -27,24 +27,16 @@ use std::collections::HashMap;
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr, CString};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::ptr;
|
|
||||||
use std::str;
|
use std::str;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::sync::mpsc::channel;
|
use std::sync::mpsc::channel;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use libc::{self, c_uint, c_int, c_void};
|
use libc::{c_uint, c_int, c_void};
|
||||||
|
|
||||||
pub fn llvm_err(handler: &errors::Handler, msg: String) -> ! {
|
pub fn llvm_err(handler: &errors::Handler, msg: String) -> ! {
|
||||||
unsafe {
|
match llvm::last_error() {
|
||||||
let cstr = llvm::LLVMRustGetLastError();
|
Some(err) => panic!(handler.fatal(&format!("{}: {}", msg, err))),
|
||||||
if cstr == ptr::null() {
|
None => panic!(handler.fatal(&msg)),
|
||||||
panic!(handler.fatal(&msg[..]));
|
|
||||||
} else {
|
|
||||||
let err = CStr::from_ptr(cstr).to_bytes();
|
|
||||||
let err = String::from_utf8_lossy(err).to_string();
|
|
||||||
libc::free(cstr as *mut _);
|
|
||||||
panic!(handler.fatal(&format!("{}: {}", &msg[..], &err[..])));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1271,7 +1271,8 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Variant(_, ref repr, _, _) => {
|
Variant(_, ref repr, _, _) => {
|
||||||
let (the_kind, val_opt) = adt::trans_switch(bcx, &**repr, val.val);
|
let (the_kind, val_opt) = adt::trans_switch(bcx, &repr,
|
||||||
|
val.val, true);
|
||||||
kind = the_kind;
|
kind = the_kind;
|
||||||
if let Some(tval) = val_opt { test_val = tval; }
|
if let Some(tval) = val_opt { test_val = tval; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -890,12 +890,15 @@ fn struct_llfields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, st: &Struct<'tcx>,
|
||||||
///
|
///
|
||||||
/// This should ideally be less tightly tied to `_match`.
|
/// This should ideally be less tightly tied to `_match`.
|
||||||
pub fn trans_switch<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
pub fn trans_switch<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||||
r: &Repr<'tcx>, scrutinee: ValueRef)
|
r: &Repr<'tcx>,
|
||||||
|
scrutinee: ValueRef,
|
||||||
|
range_assert: bool)
|
||||||
-> (_match::BranchKind, Option<ValueRef>) {
|
-> (_match::BranchKind, Option<ValueRef>) {
|
||||||
match *r {
|
match *r {
|
||||||
CEnum(..) | General(..) |
|
CEnum(..) | General(..) |
|
||||||
RawNullablePointer { .. } | StructWrappedNullablePointer { .. } => {
|
RawNullablePointer { .. } | StructWrappedNullablePointer { .. } => {
|
||||||
(_match::Switch, Some(trans_get_discr(bcx, r, scrutinee, None)))
|
(_match::Switch, Some(trans_get_discr(bcx, r, scrutinee, None,
|
||||||
|
range_assert)))
|
||||||
}
|
}
|
||||||
Univariant(..) => {
|
Univariant(..) => {
|
||||||
// N.B.: Univariant means <= 1 enum variants (*not* == 1 variants).
|
// N.B.: Univariant means <= 1 enum variants (*not* == 1 variants).
|
||||||
|
@ -916,14 +919,18 @@ pub fn is_discr_signed<'tcx>(r: &Repr<'tcx>) -> bool {
|
||||||
|
|
||||||
/// Obtain the actual discriminant of a value.
|
/// Obtain the actual discriminant of a value.
|
||||||
pub fn trans_get_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
|
pub fn trans_get_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
|
||||||
scrutinee: ValueRef, cast_to: Option<Type>)
|
scrutinee: ValueRef, cast_to: Option<Type>,
|
||||||
|
range_assert: bool)
|
||||||
-> ValueRef {
|
-> ValueRef {
|
||||||
debug!("trans_get_discr r: {:?}", r);
|
debug!("trans_get_discr r: {:?}", r);
|
||||||
let val = match *r {
|
let val = match *r {
|
||||||
CEnum(ity, min, max) => load_discr(bcx, ity, scrutinee, min, max),
|
CEnum(ity, min, max) => {
|
||||||
|
load_discr(bcx, ity, scrutinee, min, max, range_assert)
|
||||||
|
}
|
||||||
General(ity, ref cases, _) => {
|
General(ity, ref cases, _) => {
|
||||||
let ptr = StructGEP(bcx, scrutinee, 0);
|
let ptr = StructGEP(bcx, scrutinee, 0);
|
||||||
load_discr(bcx, ity, ptr, Disr(0), Disr(cases.len() as u64 - 1))
|
load_discr(bcx, ity, ptr, Disr(0), Disr(cases.len() as u64 - 1),
|
||||||
|
range_assert)
|
||||||
}
|
}
|
||||||
Univariant(..) => C_u8(bcx.ccx(), 0),
|
Univariant(..) => C_u8(bcx.ccx(), 0),
|
||||||
RawNullablePointer { nndiscr, nnty, .. } => {
|
RawNullablePointer { nndiscr, nnty, .. } => {
|
||||||
|
@ -950,7 +957,8 @@ fn struct_wrapped_nullable_bitdiscr(bcx: Block, nndiscr: Disr, discrfield: &Disc
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper for cases where the discriminant is simply loaded.
|
/// Helper for cases where the discriminant is simply loaded.
|
||||||
fn load_discr(bcx: Block, ity: IntType, ptr: ValueRef, min: Disr, max: Disr)
|
fn load_discr(bcx: Block, ity: IntType, ptr: ValueRef, min: Disr, max: Disr,
|
||||||
|
range_assert: bool)
|
||||||
-> ValueRef {
|
-> ValueRef {
|
||||||
let llty = ll_inttype(bcx.ccx(), ity);
|
let llty = ll_inttype(bcx.ccx(), ity);
|
||||||
assert_eq!(val_ty(ptr), llty.ptr_to());
|
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)
|
||||||
let mask = Disr(!0u64 >> (64 - bits));
|
let mask = Disr(!0u64 >> (64 - bits));
|
||||||
// For a (max) discr of -1, max will be `-1 as usize`, which overflows.
|
// For a (max) discr of -1, max will be `-1 as usize`, which overflows.
|
||||||
// However, that is fine here (it would still represent the full range),
|
// However, that is fine here (it would still represent the full range),
|
||||||
if max.wrapping_add(Disr(1)) & mask == min & mask {
|
if max.wrapping_add(Disr(1)) & mask == min & mask || !range_assert {
|
||||||
// i.e., if the range is everything. The lo==hi case would be
|
// i.e., if the range is everything. The lo==hi case would be
|
||||||
// rejected by the LLVM verifier (it would mean either an
|
// rejected by the LLVM verifier (it would mean either an
|
||||||
// empty set, which is impossible, or the entire range of the
|
// 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>,
|
||||||
// runtime, so the basic block isn't actually unreachable, so we
|
// runtime, so the basic block isn't actually unreachable, so we
|
||||||
// need to make it do something with defined behavior. In this case
|
// need to make it do something with defined behavior. In this case
|
||||||
// we just return early from the function.
|
// we just return early from the function.
|
||||||
|
//
|
||||||
|
// Note that this is also why the `trans_get_discr` below has
|
||||||
|
// `false` to indicate that loading the discriminant should
|
||||||
|
// not have a range assert.
|
||||||
let ret_void_cx = fcx.new_temp_block("enum-variant-iter-ret-void");
|
let ret_void_cx = fcx.new_temp_block("enum-variant-iter-ret-void");
|
||||||
RetVoid(ret_void_cx, DebugLoc::None);
|
RetVoid(ret_void_cx, DebugLoc::None);
|
||||||
|
|
||||||
let discr_val = trans_get_discr(bcx, r, value, None);
|
let discr_val = trans_get_discr(bcx, r, value, None, false);
|
||||||
let llswitch = Switch(bcx, discr_val, ret_void_cx.llbb, cases.len());
|
let llswitch = Switch(bcx, discr_val, ret_void_cx.llbb, cases.len());
|
||||||
let bcx_next = fcx.new_temp_block("enum-variant-iter-next");
|
let bcx_next = fcx.new_temp_block("enum-variant-iter-next");
|
||||||
|
|
||||||
|
|
|
@ -556,7 +556,7 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
|
||||||
// NB: we must hit the discriminant first so that structural
|
// NB: we must hit the discriminant first so that structural
|
||||||
// comparison know not to proceed when the discriminants differ.
|
// comparison know not to proceed when the discriminants differ.
|
||||||
|
|
||||||
match adt::trans_switch(cx, &*repr, av) {
|
match adt::trans_switch(cx, &*repr, av, false) {
|
||||||
(_match::Single, None) => {
|
(_match::Single, None) => {
|
||||||
if n_variants != 0 {
|
if n_variants != 0 {
|
||||||
assert!(n_variants == 1);
|
assert!(n_variants == 1);
|
||||||
|
|
|
@ -2116,7 +2116,8 @@ fn trans_imm_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||||
let datum = unpack_datum!(
|
let datum = unpack_datum!(
|
||||||
bcx, datum.to_lvalue_datum(bcx, "trans_imm_cast", expr.id));
|
bcx, datum.to_lvalue_datum(bcx, "trans_imm_cast", expr.id));
|
||||||
let llexpr_ptr = datum.to_llref();
|
let llexpr_ptr = datum.to_llref();
|
||||||
let discr = adt::trans_get_discr(bcx, &*repr, llexpr_ptr, Some(Type::i64(ccx)));
|
let discr = adt::trans_get_discr(bcx, &*repr, llexpr_ptr,
|
||||||
|
Some(Type::i64(ccx)), true);
|
||||||
ll_t_in = val_ty(discr);
|
ll_t_in = val_ty(discr);
|
||||||
(discr, adt::is_discr_signed(&*repr))
|
(discr, adt::is_discr_signed(&*repr))
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -655,7 +655,8 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
||||||
match val_ty.sty {
|
match val_ty.sty {
|
||||||
ty::TyEnum(..) => {
|
ty::TyEnum(..) => {
|
||||||
let repr = adt::represent_type(ccx, *val_ty);
|
let repr = adt::represent_type(ccx, *val_ty);
|
||||||
adt::trans_get_discr(bcx, &*repr, llargs[0], Some(llret_ty))
|
adt::trans_get_discr(bcx, &*repr, llargs[0],
|
||||||
|
Some(llret_ty), true)
|
||||||
}
|
}
|
||||||
_ => C_null(llret_ty)
|
_ => C_null(llret_ty)
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||||
let discr_lvalue = self.trans_lvalue(bcx, discr);
|
let discr_lvalue = self.trans_lvalue(bcx, discr);
|
||||||
let ty = discr_lvalue.ty.to_ty(bcx.tcx());
|
let ty = discr_lvalue.ty.to_ty(bcx.tcx());
|
||||||
let repr = adt::represent_type(bcx.ccx(), ty);
|
let repr = adt::represent_type(bcx.ccx(), ty);
|
||||||
let discr = adt::trans_get_discr(bcx, &repr, discr_lvalue.llval, None);
|
let discr = adt::trans_get_discr(bcx, &repr, discr_lvalue.llval,
|
||||||
|
None, true);
|
||||||
|
|
||||||
// The else branch of the Switch can't be hit, so branch to an unreachable
|
// The else branch of the Switch can't be hit, so branch to an unreachable
|
||||||
// instruction so LLVM knows that
|
// instruction so LLVM knows that
|
||||||
|
|
2
src/llvm
2
src/llvm
|
@ -1 +1 @@
|
||||||
Subproject commit 3564439515985dc1cc0d77057ed00901635a80ad
|
Subproject commit de5c31045dc0f6da1f65d02ee640ccf99ba90e7c
|
|
@ -24,7 +24,13 @@ struct LLVMRustArchiveMember {
|
||||||
const char *name;
|
const char *name;
|
||||||
Archive::Child child;
|
Archive::Child child;
|
||||||
|
|
||||||
LLVMRustArchiveMember(): filename(NULL), name(NULL), child(NULL, NULL) {}
|
LLVMRustArchiveMember(): filename(NULL), name(NULL),
|
||||||
|
#if LLVM_VERSION_MINOR >= 8
|
||||||
|
child(NULL, NULL, NULL)
|
||||||
|
#else
|
||||||
|
child(NULL, NULL)
|
||||||
|
#endif
|
||||||
|
{}
|
||||||
~LLVMRustArchiveMember() {}
|
~LLVMRustArchiveMember() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -92,8 +98,18 @@ extern "C" const Archive::Child*
|
||||||
LLVMRustArchiveIteratorNext(RustArchiveIterator *rai) {
|
LLVMRustArchiveIteratorNext(RustArchiveIterator *rai) {
|
||||||
if (rai->cur == rai->end)
|
if (rai->cur == rai->end)
|
||||||
return NULL;
|
return NULL;
|
||||||
const Archive::Child *cur = rai->cur.operator->();
|
#if LLVM_VERSION_MINOR >= 8
|
||||||
Archive::Child *ret = new Archive::Child(*cur);
|
const ErrorOr<Archive::Child>* cur = rai->cur.operator->();
|
||||||
|
if (!*cur) {
|
||||||
|
LLVMRustSetLastError(cur->getError().message().c_str());
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
const Archive::Child &child = cur->get();
|
||||||
|
#else
|
||||||
|
const Archive::Child &child = *rai->cur.operator->();
|
||||||
|
#endif
|
||||||
|
Archive::Child *ret = new Archive::Child(child);
|
||||||
|
|
||||||
++rai->cur;
|
++rai->cur;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -348,6 +348,19 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateFunction(
|
||||||
LLVMValueRef Fn,
|
LLVMValueRef Fn,
|
||||||
LLVMMetadataRef TParam,
|
LLVMMetadataRef TParam,
|
||||||
LLVMMetadataRef Decl) {
|
LLVMMetadataRef Decl) {
|
||||||
|
#if LLVM_VERSION_MINOR >= 8
|
||||||
|
DITemplateParameterArray TParams =
|
||||||
|
DITemplateParameterArray(unwrap<MDTuple>(TParam));
|
||||||
|
DISubprogram *Sub = Builder->createFunction(
|
||||||
|
unwrapDI<DIScope>(Scope), Name, LinkageName,
|
||||||
|
unwrapDI<DIFile>(File), LineNo,
|
||||||
|
unwrapDI<DISubroutineType>(Ty), isLocalToUnit, isDefinition, ScopeLine,
|
||||||
|
Flags, isOptimized,
|
||||||
|
TParams,
|
||||||
|
unwrapDIptr<DISubprogram>(Decl));
|
||||||
|
unwrap<Function>(Fn)->setSubprogram(Sub);
|
||||||
|
return wrap(Sub);
|
||||||
|
#else
|
||||||
return wrap(Builder->createFunction(
|
return wrap(Builder->createFunction(
|
||||||
unwrapDI<DIScope>(Scope), Name, LinkageName,
|
unwrapDI<DIScope>(Scope), Name, LinkageName,
|
||||||
unwrapDI<DIFile>(File), LineNo,
|
unwrapDI<DIFile>(File), LineNo,
|
||||||
|
@ -356,6 +369,7 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateFunction(
|
||||||
unwrap<Function>(Fn),
|
unwrap<Function>(Fn),
|
||||||
unwrapDIptr<MDNode>(TParam),
|
unwrapDIptr<MDNode>(TParam),
|
||||||
unwrapDIptr<MDNode>(Decl)));
|
unwrapDIptr<MDNode>(Decl)));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" LLVMMetadataRef LLVMDIBuilderCreateBasicType(
|
extern "C" LLVMMetadataRef LLVMDIBuilderCreateBasicType(
|
||||||
|
@ -830,7 +844,9 @@ LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) {
|
||||||
#if LLVM_VERSION_MINOR >= 6
|
#if LLVM_VERSION_MINOR >= 6
|
||||||
raw_string_ostream Stream(Err);
|
raw_string_ostream Stream(Err);
|
||||||
DiagnosticPrinterRawOStream DP(Stream);
|
DiagnosticPrinterRawOStream DP(Stream);
|
||||||
#if LLVM_VERSION_MINOR >= 7
|
#if LLVM_VERSION_MINOR >= 8
|
||||||
|
if (Linker::linkModules(*Dst, std::move(Src.get()))) {
|
||||||
|
#elif LLVM_VERSION_MINOR >= 7
|
||||||
if (Linker::LinkModules(Dst, Src->get(), [&](const DiagnosticInfo &DI) { DI.print(DP); })) {
|
if (Linker::LinkModules(Dst, Src->get(), [&](const DiagnosticInfo &DI) { DI.print(DP); })) {
|
||||||
#else
|
#else
|
||||||
if (Linker::LinkModules(Dst, *Src, [&](const DiagnosticInfo &DI) { DI.print(DP); })) {
|
if (Linker::LinkModules(Dst, *Src, [&](const DiagnosticInfo &DI) { DI.print(DP); })) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# If this file is modified, then llvm will be forcibly cleaned and then rebuilt.
|
# If this file is modified, then llvm will be forcibly cleaned and then rebuilt.
|
||||||
# The actual contents of this file do not matter, but to trigger a change on the
|
# The actual contents of this file do not matter, but to trigger a change on the
|
||||||
# build bots then the contents should be changed so git updates the mtime.
|
# build bots then the contents should be changed so git updates the mtime.
|
||||||
2015-12-02
|
2015-01-25
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
{
|
{
|
||||||
"data-layout": "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32",
|
|
||||||
"llvm-target": "i686-unknown-linux-gnu",
|
"llvm-target": "i686-unknown-linux-gnu",
|
||||||
"target-endian": "little",
|
"target-endian": "little",
|
||||||
"target-pointer-width": "32",
|
"target-pointer-width": "32",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue