mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-29 03:27:44 +00:00
Auto merge of #38048 - rkruppe:llvm-stringref-fixes, r=alexcrichton
[LLVM 4.0] Don't assume llvm::StringRef is null terminated StringRefs have a length and their contents are not usually null-terminated. The solution is to either copy the string data (in `rustc_llvm::diagnostic`) or take the size into account (in LLVMRustPrintPasses). I couldn't trigger a bug caused by this (apparently all the strings returned in practice are actually null-terminated) but this is more correct and more future-proof. cc #37609
This commit is contained in:
commit
908dba0c94
@ -13,7 +13,7 @@
|
|||||||
pub use self::OptimizationDiagnosticKind::*;
|
pub use self::OptimizationDiagnosticKind::*;
|
||||||
pub use self::Diagnostic::*;
|
pub use self::Diagnostic::*;
|
||||||
|
|
||||||
use libc::{c_char, c_uint};
|
use libc::c_uint;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
use {DiagnosticInfoRef, TwineRef, ValueRef};
|
use {DiagnosticInfoRef, TwineRef, ValueRef};
|
||||||
@ -45,7 +45,7 @@ impl OptimizationDiagnosticKind {
|
|||||||
|
|
||||||
pub struct OptimizationDiagnostic {
|
pub struct OptimizationDiagnostic {
|
||||||
pub kind: OptimizationDiagnosticKind,
|
pub kind: OptimizationDiagnosticKind,
|
||||||
pub pass_name: *const c_char,
|
pub pass_name: String,
|
||||||
pub function: ValueRef,
|
pub function: ValueRef,
|
||||||
pub debug_loc: DebugLocRef,
|
pub debug_loc: DebugLocRef,
|
||||||
pub message: String,
|
pub message: String,
|
||||||
@ -55,21 +55,23 @@ impl OptimizationDiagnostic {
|
|||||||
unsafe fn unpack(kind: OptimizationDiagnosticKind,
|
unsafe fn unpack(kind: OptimizationDiagnosticKind,
|
||||||
di: DiagnosticInfoRef)
|
di: DiagnosticInfoRef)
|
||||||
-> OptimizationDiagnostic {
|
-> OptimizationDiagnostic {
|
||||||
let mut pass_name = ptr::null();
|
|
||||||
let mut function = ptr::null_mut();
|
let mut function = ptr::null_mut();
|
||||||
let mut debug_loc = ptr::null_mut();
|
let mut debug_loc = ptr::null_mut();
|
||||||
|
|
||||||
let message = super::build_string(|message|
|
let mut message = None;
|
||||||
|
let pass_name = super::build_string(|pass_name|
|
||||||
|
message = super::build_string(|message|
|
||||||
super::LLVMRustUnpackOptimizationDiagnostic(di,
|
super::LLVMRustUnpackOptimizationDiagnostic(di,
|
||||||
&mut pass_name,
|
pass_name,
|
||||||
&mut function,
|
&mut function,
|
||||||
&mut debug_loc,
|
&mut debug_loc,
|
||||||
message)
|
message)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
OptimizationDiagnostic {
|
OptimizationDiagnostic {
|
||||||
kind: kind,
|
kind: kind,
|
||||||
pass_name: pass_name,
|
pass_name: pass_name.expect("got a non-UTF8 pass name from LLVM"),
|
||||||
function: function,
|
function: function,
|
||||||
debug_loc: debug_loc,
|
debug_loc: debug_loc,
|
||||||
message: message.expect("got a non-UTF8 OptimizationDiagnostic message from LLVM")
|
message: message.expect("got a non-UTF8 OptimizationDiagnostic message from LLVM")
|
||||||
|
@ -1820,7 +1820,7 @@ extern "C" {
|
|||||||
DiagnosticContext: *mut c_void);
|
DiagnosticContext: *mut c_void);
|
||||||
|
|
||||||
pub fn LLVMRustUnpackOptimizationDiagnostic(DI: DiagnosticInfoRef,
|
pub fn LLVMRustUnpackOptimizationDiagnostic(DI: DiagnosticInfoRef,
|
||||||
pass_name_out: *mut *const c_char,
|
pass_name_out: RustStringRef,
|
||||||
function_out: *mut ValueRef,
|
function_out: *mut ValueRef,
|
||||||
debugloc_out: *mut DebugLocRef,
|
debugloc_out: *mut DebugLocRef,
|
||||||
message_out: RustStringRef);
|
message_out: RustStringRef);
|
||||||
|
@ -26,7 +26,7 @@ use errors::emitter::Emitter;
|
|||||||
use syntax_pos::MultiSpan;
|
use syntax_pos::MultiSpan;
|
||||||
use context::{is_pie_binary, get_reloc_model};
|
use context::{is_pie_binary, get_reloc_model};
|
||||||
|
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::CString;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::str;
|
use std::str;
|
||||||
@ -403,19 +403,16 @@ unsafe extern "C" fn diagnostic_handler(info: DiagnosticInfoRef, user: *mut c_vo
|
|||||||
}
|
}
|
||||||
|
|
||||||
llvm::diagnostic::Optimization(opt) => {
|
llvm::diagnostic::Optimization(opt) => {
|
||||||
let pass_name = str::from_utf8(CStr::from_ptr(opt.pass_name).to_bytes())
|
|
||||||
.ok()
|
|
||||||
.expect("got a non-UTF8 pass name from LLVM");
|
|
||||||
let enabled = match cgcx.remark {
|
let enabled = match cgcx.remark {
|
||||||
AllPasses => true,
|
AllPasses => true,
|
||||||
SomePasses(ref v) => v.iter().any(|s| *s == pass_name),
|
SomePasses(ref v) => v.iter().any(|s| *s == opt.pass_name),
|
||||||
};
|
};
|
||||||
|
|
||||||
if enabled {
|
if enabled {
|
||||||
let loc = llvm::debug_loc_to_string(llcx, opt.debug_loc);
|
let loc = llvm::debug_loc_to_string(llcx, opt.debug_loc);
|
||||||
cgcx.handler.note_without_error(&format!("optimization {} for {} at {}: {}",
|
cgcx.handler.note_without_error(&format!("optimization {} for {} at {}: {}",
|
||||||
opt.kind.describe(),
|
opt.kind.describe(),
|
||||||
pass_name,
|
opt.pass_name,
|
||||||
if loc.is_empty() { "[unknown]" } else { &*loc },
|
if loc.is_empty() { "[unknown]" } else { &*loc },
|
||||||
opt.message));
|
opt.message));
|
||||||
}
|
}
|
||||||
|
@ -530,9 +530,11 @@ LLVMRustPrintPasses() {
|
|||||||
struct MyListener : PassRegistrationListener {
|
struct MyListener : PassRegistrationListener {
|
||||||
void passEnumerate(const PassInfo *info) {
|
void passEnumerate(const PassInfo *info) {
|
||||||
#if LLVM_VERSION_GE(4, 0)
|
#if LLVM_VERSION_GE(4, 0)
|
||||||
if (!info->getPassArgument().empty()) {
|
StringRef PassArg = info->getPassArgument();
|
||||||
printf("%15s - %s\n", info->getPassArgument().data(),
|
StringRef PassName = info->getPassName();
|
||||||
info->getPassName().data());
|
if (!PassArg.empty()) {
|
||||||
|
printf("%15.*s - %.*s\n", PassArg.size(), PassArg.data(),
|
||||||
|
PassName.size(), PassName.data());
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (info->getPassArgument() && *info->getPassArgument()) {
|
if (info->getPassArgument() && *info->getPassArgument()) {
|
||||||
|
@ -872,7 +872,7 @@ LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef str) {
|
|||||||
extern "C" void
|
extern "C" void
|
||||||
LLVMRustUnpackOptimizationDiagnostic(
|
LLVMRustUnpackOptimizationDiagnostic(
|
||||||
LLVMDiagnosticInfoRef di,
|
LLVMDiagnosticInfoRef di,
|
||||||
const char **pass_name_out,
|
RustStringRef pass_name_out,
|
||||||
LLVMValueRef *function_out,
|
LLVMValueRef *function_out,
|
||||||
LLVMDebugLocRef *debugloc_out,
|
LLVMDebugLocRef *debugloc_out,
|
||||||
RustStringRef message_out)
|
RustStringRef message_out)
|
||||||
@ -881,15 +881,12 @@ LLVMRustUnpackOptimizationDiagnostic(
|
|||||||
llvm::DiagnosticInfoOptimizationBase *opt
|
llvm::DiagnosticInfoOptimizationBase *opt
|
||||||
= static_cast<llvm::DiagnosticInfoOptimizationBase*>(unwrap(di));
|
= static_cast<llvm::DiagnosticInfoOptimizationBase*>(unwrap(di));
|
||||||
|
|
||||||
#if LLVM_VERSION_GE(4, 0)
|
raw_rust_string_ostream pass_name_os(pass_name_out);
|
||||||
*pass_name_out = opt->getPassName().data();
|
pass_name_os << opt->getPassName();
|
||||||
#else
|
|
||||||
*pass_name_out = opt->getPassName();
|
|
||||||
#endif
|
|
||||||
*function_out = wrap(&opt->getFunction());
|
*function_out = wrap(&opt->getFunction());
|
||||||
*debugloc_out = wrap(&opt->getDebugLoc());
|
*debugloc_out = wrap(&opt->getDebugLoc());
|
||||||
raw_rust_string_ostream os(message_out);
|
raw_rust_string_ostream message_os(message_out);
|
||||||
os << opt->getMsg();
|
message_os << opt->getMsg();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void
|
extern "C" void
|
||||||
|
Loading…
Reference in New Issue
Block a user