parent
225353d8bb
commit
ad9a1daa81
6 changed files with 297 additions and 13 deletions
|
@ -11,11 +11,11 @@
|
||||||
use back::lto;
|
use back::lto;
|
||||||
use back::link::{get_cc_prog, remove};
|
use back::link::{get_cc_prog, remove};
|
||||||
use driver::driver::{CrateTranslation, ModuleTranslation, OutputFilenames};
|
use driver::driver::{CrateTranslation, ModuleTranslation, OutputFilenames};
|
||||||
use driver::config::NoDebugInfo;
|
use driver::config::{NoDebugInfo, Passes, AllPasses};
|
||||||
use driver::session::Session;
|
use driver::session::Session;
|
||||||
use driver::config;
|
use driver::config;
|
||||||
use llvm;
|
use llvm;
|
||||||
use llvm::{ModuleRef, TargetMachineRef, PassManagerRef};
|
use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef, ContextRef};
|
||||||
use util::common::time;
|
use util::common::time;
|
||||||
use syntax::abi;
|
use syntax::abi;
|
||||||
use syntax::codemap;
|
use syntax::codemap;
|
||||||
|
@ -28,9 +28,10 @@ use std::io::fs;
|
||||||
use std::iter::Unfold;
|
use std::iter::Unfold;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
use std::mem;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::task::TaskBuilder;
|
use std::task::TaskBuilder;
|
||||||
use libc::{c_uint, c_int};
|
use libc::{c_uint, c_int, c_void};
|
||||||
|
|
||||||
|
|
||||||
#[deriving(Clone, PartialEq, PartialOrd, Ord, Eq)]
|
#[deriving(Clone, PartialEq, PartialOrd, Ord, Eq)]
|
||||||
|
@ -311,24 +312,52 @@ struct CodegenContext<'a> {
|
||||||
lto_ctxt: Option<(&'a Session, &'a [String])>,
|
lto_ctxt: Option<(&'a Session, &'a [String])>,
|
||||||
// Handler to use for diagnostics produced during codegen.
|
// Handler to use for diagnostics produced during codegen.
|
||||||
handler: &'a Handler,
|
handler: &'a Handler,
|
||||||
|
// LLVM optimizations for which we want to print remarks.
|
||||||
|
remark: Passes,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> CodegenContext<'a> {
|
impl<'a> CodegenContext<'a> {
|
||||||
fn new(handler: &'a Handler) -> CodegenContext<'a> {
|
|
||||||
CodegenContext {
|
|
||||||
lto_ctxt: None,
|
|
||||||
handler: handler,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_with_session(sess: &'a Session, reachable: &'a [String]) -> CodegenContext<'a> {
|
fn new_with_session(sess: &'a Session, reachable: &'a [String]) -> CodegenContext<'a> {
|
||||||
CodegenContext {
|
CodegenContext {
|
||||||
lto_ctxt: Some((sess, reachable)),
|
lto_ctxt: Some((sess, reachable)),
|
||||||
handler: sess.diagnostic().handler(),
|
handler: sess.diagnostic().handler(),
|
||||||
|
remark: sess.opts.cg.remark.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct DiagHandlerFreeVars<'a> {
|
||||||
|
llcx: ContextRef,
|
||||||
|
cgcx: &'a CodegenContext<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn diagnostic_handler(info: DiagnosticInfoRef, user: *mut c_void) {
|
||||||
|
let DiagHandlerFreeVars { llcx, cgcx }
|
||||||
|
= *mem::transmute::<_, *const DiagHandlerFreeVars>(user);
|
||||||
|
|
||||||
|
match llvm::diagnostic::Diagnostic::unpack(info) {
|
||||||
|
llvm::diagnostic::Optimization(opt) => {
|
||||||
|
let pass_name = CString::new(opt.pass_name, false);
|
||||||
|
let pass_name = pass_name.as_str().expect("got a non-UTF8 pass name from LLVM");
|
||||||
|
let enabled = match cgcx.remark {
|
||||||
|
AllPasses => true,
|
||||||
|
Passes(ref v) => v.iter().any(|s| s.as_slice() == pass_name),
|
||||||
|
};
|
||||||
|
|
||||||
|
if enabled {
|
||||||
|
let loc = llvm::debug_loc_to_string(llcx, opt.debug_loc);
|
||||||
|
cgcx.handler.note(format!("optimization {:s} for {:s} at {:s}: {:s}",
|
||||||
|
opt.kind.describe(),
|
||||||
|
pass_name,
|
||||||
|
if loc.is_empty() { "[unknown]" } else { loc.as_slice() },
|
||||||
|
llvm::twine_to_string(opt.message)).as_slice());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Unsafe due to LLVM calls.
|
// Unsafe due to LLVM calls.
|
||||||
unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
|
unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
|
||||||
mtrans: ModuleTranslation,
|
mtrans: ModuleTranslation,
|
||||||
|
@ -338,6 +367,17 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
|
||||||
let ModuleTranslation { llmod, llcx } = mtrans;
|
let ModuleTranslation { llmod, llcx } = mtrans;
|
||||||
let tm = config.tm;
|
let tm = config.tm;
|
||||||
|
|
||||||
|
// llcx doesn't outlive this function, so we can put this on the stack.
|
||||||
|
let fv = DiagHandlerFreeVars {
|
||||||
|
llcx: llcx,
|
||||||
|
cgcx: cgcx,
|
||||||
|
};
|
||||||
|
if !cgcx.remark.is_empty() {
|
||||||
|
llvm::LLVMContextSetDiagnosticHandler(llcx, diagnostic_handler,
|
||||||
|
&fv as *const DiagHandlerFreeVars
|
||||||
|
as *mut c_void);
|
||||||
|
}
|
||||||
|
|
||||||
if config.emit_no_opt_bc {
|
if config.emit_no_opt_bc {
|
||||||
let ext = format!("{}.no-opt.bc", name_extra);
|
let ext = format!("{}.no-opt.bc", name_extra);
|
||||||
output_names.with_extension(ext.as_slice()).with_c_str(|buf| {
|
output_names.with_extension(ext.as_slice()).with_c_str(|buf| {
|
||||||
|
@ -785,13 +825,18 @@ fn run_work_multithreaded(sess: &Session,
|
||||||
for i in range(0, num_workers) {
|
for i in range(0, num_workers) {
|
||||||
let work_items_arc = work_items_arc.clone();
|
let work_items_arc = work_items_arc.clone();
|
||||||
let diag_emitter = diag_emitter.clone();
|
let diag_emitter = diag_emitter.clone();
|
||||||
|
let remark = sess.opts.cg.remark.clone();
|
||||||
|
|
||||||
let future = TaskBuilder::new().named(format!("codegen-{}", i)).try_future(proc() {
|
let future = TaskBuilder::new().named(format!("codegen-{}", i)).try_future(proc() {
|
||||||
let diag_handler = mk_handler(box diag_emitter);
|
let diag_handler = mk_handler(box diag_emitter);
|
||||||
|
|
||||||
// Must construct cgcx inside the proc because it has non-Send
|
// Must construct cgcx inside the proc because it has non-Send
|
||||||
// fields.
|
// fields.
|
||||||
let cgcx = CodegenContext::new(&diag_handler);
|
let cgcx = CodegenContext {
|
||||||
|
lto_ctxt: None,
|
||||||
|
handler: &diag_handler,
|
||||||
|
remark: remark,
|
||||||
|
};
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// Avoid holding the lock for the entire duration of the match.
|
// Avoid holding the lock for the entire duration of the match.
|
||||||
|
|
|
@ -235,6 +235,21 @@ pub fn debugging_opts_map() -> Vec<(&'static str, &'static str, u64)> {
|
||||||
--pretty flowgraph output", FLOWGRAPH_PRINT_ALL))
|
--pretty flowgraph output", FLOWGRAPH_PRINT_ALL))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deriving(Clone)]
|
||||||
|
pub enum Passes {
|
||||||
|
Passes(Vec<String>),
|
||||||
|
AllPasses,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Passes {
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
Passes(ref v) => v.is_empty(),
|
||||||
|
AllPasses => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Declare a macro that will define all CodegenOptions fields and parsers all
|
/// Declare a macro that will define all CodegenOptions fields and parsers all
|
||||||
/// at once. The goal of this macro is to define an interface that can be
|
/// at once. The goal of this macro is to define an interface that can be
|
||||||
/// programmatically used by the option parser in order to initialize the struct
|
/// programmatically used by the option parser in order to initialize the struct
|
||||||
|
@ -261,7 +276,7 @@ macro_rules! cgoptions(
|
||||||
&[ $( (stringify!($opt), cgsetters::$opt, $desc) ),* ];
|
&[ $( (stringify!($opt), cgsetters::$opt, $desc) ),* ];
|
||||||
|
|
||||||
mod cgsetters {
|
mod cgsetters {
|
||||||
use super::CodegenOptions;
|
use super::{CodegenOptions, Passes, AllPasses};
|
||||||
|
|
||||||
$(
|
$(
|
||||||
pub fn $opt(cg: &mut CodegenOptions, v: Option<&str>) -> bool {
|
pub fn $opt(cg: &mut CodegenOptions, v: Option<&str>) -> bool {
|
||||||
|
@ -310,6 +325,24 @@ macro_rules! cgoptions(
|
||||||
None => false
|
None => false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_passes(slot: &mut Passes, v: Option<&str>) -> bool {
|
||||||
|
match v {
|
||||||
|
Some("all") => {
|
||||||
|
*slot = AllPasses;
|
||||||
|
true
|
||||||
|
}
|
||||||
|
v => {
|
||||||
|
let mut passes = vec!();
|
||||||
|
if parse_list(&mut passes, v) {
|
||||||
|
*slot = Passes(passes);
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
) )
|
) )
|
||||||
|
|
||||||
|
@ -356,6 +389,8 @@ cgoptions!(
|
||||||
"extra data to put in each output filename"),
|
"extra data to put in each output filename"),
|
||||||
codegen_units: uint = (1, parse_uint,
|
codegen_units: uint = (1, parse_uint,
|
||||||
"divide crate into N units to optimize in parallel"),
|
"divide crate into N units to optimize in parallel"),
|
||||||
|
remark: Passes = (Passes(Vec::new()), parse_passes,
|
||||||
|
"print remarks for these optimization passes (space separated, or \"all\")"),
|
||||||
)
|
)
|
||||||
|
|
||||||
pub fn build_codegen_options(matches: &getopts::Matches) -> CodegenOptions
|
pub fn build_codegen_options(matches: &getopts::Matches) -> CodegenOptions
|
||||||
|
@ -744,6 +779,10 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
|
||||||
}
|
}
|
||||||
let cg = build_codegen_options(matches);
|
let cg = build_codegen_options(matches);
|
||||||
|
|
||||||
|
if !cg.remark.is_empty() && debuginfo == NoDebugInfo {
|
||||||
|
early_warn("-C remark will not show source locations without --debuginfo");
|
||||||
|
}
|
||||||
|
|
||||||
let color = match matches.opt_str("color").as_ref().map(|s| s.as_slice()) {
|
let color = match matches.opt_str("color").as_ref().map(|s| s.as_slice()) {
|
||||||
Some("auto") => Auto,
|
Some("auto") => Auto,
|
||||||
Some("always") => Always,
|
Some("always") => Always,
|
||||||
|
|
92
src/librustc_llvm/diagnostic.rs
Normal file
92
src/librustc_llvm/diagnostic.rs
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
//! LLVM diagnostic reports.
|
||||||
|
|
||||||
|
use libc::c_char;
|
||||||
|
|
||||||
|
use {ValueRef, TwineRef, DebugLocRef, DiagnosticInfoRef};
|
||||||
|
|
||||||
|
pub enum OptimizationDiagnosticKind {
|
||||||
|
OptimizationRemark,
|
||||||
|
OptimizationMissed,
|
||||||
|
OptimizationAnalysis,
|
||||||
|
OptimizationFailure,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OptimizationDiagnosticKind {
|
||||||
|
pub fn describe(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
OptimizationRemark => "remark",
|
||||||
|
OptimizationMissed => "missed",
|
||||||
|
OptimizationAnalysis => "analysis",
|
||||||
|
OptimizationFailure => "failure",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct OptimizationDiagnostic {
|
||||||
|
pub kind: OptimizationDiagnosticKind,
|
||||||
|
pub pass_name: *const c_char,
|
||||||
|
pub function: ValueRef,
|
||||||
|
pub debug_loc: DebugLocRef,
|
||||||
|
pub message: TwineRef,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OptimizationDiagnostic {
|
||||||
|
unsafe fn unpack(kind: OptimizationDiagnosticKind, di: DiagnosticInfoRef)
|
||||||
|
-> OptimizationDiagnostic {
|
||||||
|
|
||||||
|
let mut opt = OptimizationDiagnostic {
|
||||||
|
kind: kind,
|
||||||
|
pass_name: 0 as *const c_char,
|
||||||
|
function: 0 as ValueRef,
|
||||||
|
debug_loc: 0 as DebugLocRef,
|
||||||
|
message: 0 as TwineRef,
|
||||||
|
};
|
||||||
|
|
||||||
|
super::LLVMUnpackOptimizationDiagnostic(di,
|
||||||
|
&mut opt.pass_name,
|
||||||
|
&mut opt.function,
|
||||||
|
&mut opt.debug_loc,
|
||||||
|
&mut opt.message);
|
||||||
|
|
||||||
|
opt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Diagnostic {
|
||||||
|
Optimization(OptimizationDiagnostic),
|
||||||
|
|
||||||
|
/// LLVM has other types that we do not wrap here.
|
||||||
|
UnknownDiagnostic(DiagnosticInfoRef),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Diagnostic {
|
||||||
|
pub unsafe fn unpack(di: DiagnosticInfoRef) -> Diagnostic {
|
||||||
|
let kind = super::LLVMGetDiagInfoKind(di);
|
||||||
|
|
||||||
|
match kind {
|
||||||
|
super::DK_OptimizationRemark
|
||||||
|
=> Optimization(OptimizationDiagnostic::unpack(OptimizationRemark, di)),
|
||||||
|
|
||||||
|
super::DK_OptimizationRemarkMissed
|
||||||
|
=> Optimization(OptimizationDiagnostic::unpack(OptimizationMissed, di)),
|
||||||
|
|
||||||
|
super::DK_OptimizationRemarkAnalysis
|
||||||
|
=> Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysis, di)),
|
||||||
|
|
||||||
|
super::DK_OptimizationFailure
|
||||||
|
=> Optimization(OptimizationDiagnostic::unpack(OptimizationFailure, di)),
|
||||||
|
|
||||||
|
_ => UnknownDiagnostic(di)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -31,13 +31,14 @@ use std::c_str::ToCStr;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::{raw, mem};
|
use std::{raw, mem};
|
||||||
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};
|
||||||
use libc::{c_longlong, c_ulonglong};
|
use libc::{c_longlong, c_ulonglong, c_void};
|
||||||
use debuginfo::{DIBuilderRef, DIDescriptor,
|
use debuginfo::{DIBuilderRef, DIDescriptor,
|
||||||
DIFile, DILexicalBlock, DISubprogram, DIType,
|
DIFile, DILexicalBlock, DISubprogram, DIType,
|
||||||
DIBasicType, DIDerivedType, DICompositeType,
|
DIBasicType, DIDerivedType, DICompositeType,
|
||||||
DIVariable, DIGlobalVariable, DIArray, DISubrange};
|
DIVariable, DIGlobalVariable, DIArray, DISubrange};
|
||||||
|
|
||||||
pub mod archive_ro;
|
pub mod archive_ro;
|
||||||
|
pub mod diagnostic;
|
||||||
|
|
||||||
pub type Opcode = u32;
|
pub type Opcode = u32;
|
||||||
pub type Bool = c_uint;
|
pub type Bool = c_uint;
|
||||||
|
@ -81,6 +82,15 @@ pub enum Linkage {
|
||||||
CommonLinkage = 14,
|
CommonLinkage = 14,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[deriving(Show)]
|
||||||
|
pub enum DiagnosticSeverity {
|
||||||
|
Error,
|
||||||
|
Warning,
|
||||||
|
Remark,
|
||||||
|
Note,
|
||||||
|
}
|
||||||
|
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
pub enum Attribute {
|
pub enum Attribute {
|
||||||
ZExtAttribute = 1 << 0,
|
ZExtAttribute = 1 << 0,
|
||||||
|
@ -360,6 +370,18 @@ pub enum CodeGenModel {
|
||||||
CodeModelLarge = 5,
|
CodeModelLarge = 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub enum DiagnosticKind {
|
||||||
|
DK_InlineAsm = 0,
|
||||||
|
DK_StackSize,
|
||||||
|
DK_DebugMetadataVersion,
|
||||||
|
DK_SampleProfile,
|
||||||
|
DK_OptimizationRemark,
|
||||||
|
DK_OptimizationRemarkMissed,
|
||||||
|
DK_OptimizationRemarkAnalysis,
|
||||||
|
DK_OptimizationFailure,
|
||||||
|
}
|
||||||
|
|
||||||
// Opaque pointer types
|
// Opaque pointer types
|
||||||
pub enum Module_opaque {}
|
pub enum Module_opaque {}
|
||||||
pub type ModuleRef = *mut Module_opaque;
|
pub type ModuleRef = *mut Module_opaque;
|
||||||
|
@ -395,6 +417,14 @@ pub enum TargetMachine_opaque {}
|
||||||
pub type TargetMachineRef = *mut TargetMachine_opaque;
|
pub type TargetMachineRef = *mut TargetMachine_opaque;
|
||||||
pub enum Archive_opaque {}
|
pub enum Archive_opaque {}
|
||||||
pub type ArchiveRef = *mut Archive_opaque;
|
pub type ArchiveRef = *mut Archive_opaque;
|
||||||
|
pub enum Twine_opaque {}
|
||||||
|
pub type TwineRef = *mut Twine_opaque;
|
||||||
|
pub enum DiagnosticInfo_opaque {}
|
||||||
|
pub type DiagnosticInfoRef = *mut DiagnosticInfo_opaque;
|
||||||
|
pub enum DebugLoc_opaque {}
|
||||||
|
pub type DebugLocRef = *mut DebugLoc_opaque;
|
||||||
|
|
||||||
|
pub type DiagnosticHandler = unsafe extern "C" fn(DiagnosticInfoRef, *mut c_void);
|
||||||
|
|
||||||
pub mod debuginfo {
|
pub mod debuginfo {
|
||||||
use super::{ValueRef};
|
use super::{ValueRef};
|
||||||
|
@ -1918,6 +1948,24 @@ extern {
|
||||||
|
|
||||||
pub fn LLVMRustGetSectionName(SI: SectionIteratorRef,
|
pub fn LLVMRustGetSectionName(SI: SectionIteratorRef,
|
||||||
data: *mut *const c_char) -> c_int;
|
data: *mut *const c_char) -> c_int;
|
||||||
|
|
||||||
|
pub fn LLVMWriteTwineToString(T: TwineRef, s: RustStringRef);
|
||||||
|
|
||||||
|
pub fn LLVMContextSetDiagnosticHandler(C: ContextRef,
|
||||||
|
Handler: DiagnosticHandler,
|
||||||
|
DiagnosticContext: *mut c_void);
|
||||||
|
|
||||||
|
pub fn LLVMUnpackOptimizationDiagnostic(DI: DiagnosticInfoRef,
|
||||||
|
pass_name_out: *mut *const c_char,
|
||||||
|
function_out: *mut ValueRef,
|
||||||
|
debugloc_out: *mut DebugLocRef,
|
||||||
|
message_out: *mut TwineRef);
|
||||||
|
|
||||||
|
pub fn LLVMWriteDiagnosticInfoToString(DI: DiagnosticInfoRef, s: RustStringRef);
|
||||||
|
pub fn LLVMGetDiagInfoSeverity(DI: DiagnosticInfoRef) -> DiagnosticSeverity;
|
||||||
|
pub fn LLVMGetDiagInfoKind(DI: DiagnosticInfoRef) -> DiagnosticKind;
|
||||||
|
|
||||||
|
pub fn LLVMWriteDebugLocToString(C: ContextRef, DL: DebugLocRef, s: RustStringRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn SetInstructionCallConv(instr: ValueRef, cc: CallConv) {
|
pub fn SetInstructionCallConv(instr: ValueRef, cc: CallConv) {
|
||||||
|
@ -2072,6 +2120,16 @@ pub fn build_string(f: |RustStringRef|) -> Option<String> {
|
||||||
String::from_utf8(buf.unwrap()).ok()
|
String::from_utf8(buf.unwrap()).ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub unsafe fn twine_to_string(tr: TwineRef) -> String {
|
||||||
|
build_string(|s| LLVMWriteTwineToString(tr, s))
|
||||||
|
.expect("got a non-UTF8 Twine from LLVM")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn debug_loc_to_string(c: ContextRef, tr: DebugLocRef) -> String {
|
||||||
|
build_string(|s| LLVMWriteDebugLocToString(c, tr, s))
|
||||||
|
.expect("got a non-UTF8 DebugLoc from LLVM")
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME #15460 - create a public function that actually calls our
|
// FIXME #15460 - create a public function that actually calls our
|
||||||
// static LLVM symbols. Otherwise the linker will just throw llvm
|
// static LLVM symbols. Otherwise the linker will just throw llvm
|
||||||
// away. We're just calling lots of stuff until we transitively get
|
// away. We're just calling lots of stuff until we transitively get
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
#include "rustllvm.h"
|
#include "rustllvm.h"
|
||||||
#include "llvm/Object/Archive.h"
|
#include "llvm/Object/Archive.h"
|
||||||
#include "llvm/Object/ObjectFile.h"
|
#include "llvm/Object/ObjectFile.h"
|
||||||
|
#include "llvm/IR/DiagnosticInfo.h"
|
||||||
|
#include "llvm/IR/DiagnosticPrinter.h"
|
||||||
|
|
||||||
#if LLVM_VERSION_MINOR >= 5
|
#if LLVM_VERSION_MINOR >= 5
|
||||||
#include "llvm/IR/CallSite.h"
|
#include "llvm/IR/CallSite.h"
|
||||||
|
@ -823,3 +825,49 @@ extern "C" LLVMTypeRef
|
||||||
LLVMRustArrayType(LLVMTypeRef ElementType, uint64_t ElementCount) {
|
LLVMRustArrayType(LLVMTypeRef ElementType, uint64_t ElementCount) {
|
||||||
return wrap(ArrayType::get(unwrap(ElementType), ElementCount));
|
return wrap(ArrayType::get(unwrap(ElementType), ElementCount));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef)
|
||||||
|
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DebugLoc, LLVMDebugLocRef)
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
LLVMWriteTwineToString(LLVMTwineRef T, RustStringRef str) {
|
||||||
|
raw_rust_string_ostream os(str);
|
||||||
|
unwrap(T)->print(os);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
LLVMUnpackOptimizationDiagnostic(
|
||||||
|
LLVMDiagnosticInfoRef di,
|
||||||
|
const char **pass_name_out,
|
||||||
|
LLVMValueRef *function_out,
|
||||||
|
LLVMDebugLocRef *debugloc_out,
|
||||||
|
LLVMTwineRef *message_out)
|
||||||
|
{
|
||||||
|
// Undefined to call this not on an optimization diagnostic!
|
||||||
|
llvm::DiagnosticInfoOptimizationBase *opt
|
||||||
|
= static_cast<llvm::DiagnosticInfoOptimizationBase*>(unwrap(di));
|
||||||
|
|
||||||
|
*pass_name_out = opt->getPassName();
|
||||||
|
*function_out = wrap(&opt->getFunction());
|
||||||
|
*debugloc_out = wrap(&opt->getDebugLoc());
|
||||||
|
*message_out = wrap(&opt->getMsg());
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void LLVMWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef di, RustStringRef str) {
|
||||||
|
raw_rust_string_ostream os(str);
|
||||||
|
DiagnosticPrinterRawOStream dp(os);
|
||||||
|
unwrap(di)->print(dp);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int LLVMGetDiagInfoKind(LLVMDiagnosticInfoRef di) {
|
||||||
|
return unwrap(di)->getKind();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void LLVMWriteDebugLocToString(
|
||||||
|
LLVMContextRef C,
|
||||||
|
LLVMDebugLocRef dl,
|
||||||
|
RustStringRef str)
|
||||||
|
{
|
||||||
|
raw_rust_string_ostream os(str);
|
||||||
|
unwrap(dl)->print(*unwrap(C), os);
|
||||||
|
}
|
||||||
|
|
|
@ -71,6 +71,8 @@
|
||||||
void LLVMRustSetLastError(const char*);
|
void LLVMRustSetLastError(const char*);
|
||||||
|
|
||||||
typedef struct OpaqueRustString *RustStringRef;
|
typedef struct OpaqueRustString *RustStringRef;
|
||||||
|
typedef struct LLVMOpaqueTwine *LLVMTwineRef;
|
||||||
|
typedef struct LLVMOpaqueDebugLoc *LLVMDebugLocRef;
|
||||||
|
|
||||||
extern "C" void
|
extern "C" void
|
||||||
rust_llvm_string_write_impl(RustStringRef str, const char *ptr, size_t size);
|
rust_llvm_string_write_impl(RustStringRef str, const char *ptr, size_t size);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue