Auto merge of #68665 - eddyb:debuginfo-early-create-var, r=nagisa
codegen: create DIVariables ahead of using them with llvm.dbg.declare. Instead of having `rustc_codegen_llvm` bundle creation of a `DIVariable` and `llvm.dbg.declare` into a single operation, they are now two separate methods, and the `DIVariable` is created earlier, specifically when `mir::VarDebugInfo`s are being partitioned into locals. While this isn't currently needed, it's a prerequisite for #48300, which adds fragmented debuginfo, where one `mir::VarDebugInfo` has multiple parts of itself mapped to different `mir::Place`s. For debuggers to see one composite variable instead of several ones with the same name, we need to create a single `DIVariable` and share it between multiple `llvm.dbg.declare` calls, which are likely pointing to different MIR locals. That makes the `per_local_var_debug_info` partitioning a good spot to do this in, as we can create *exactly* one `DIVariable` per `mir::VarDebugInfo`, and refer to it as many things as needed. I'm opening this PR separately because I want to test its perf impact in isolation (see https://github.com/rust-lang/rust/pull/48300#issuecomment-580121438). r? @nagisa or @oli-obk cc @michaelwoerister @nikomatsakis
This commit is contained in:
commit
bdd946df3a
9 changed files with 209 additions and 94 deletions
|
@ -57,6 +57,7 @@ impl BackendTypes for Builder<'_, 'll, 'tcx> {
|
|||
type Funclet = <CodegenCx<'ll, 'tcx> as BackendTypes>::Funclet;
|
||||
|
||||
type DIScope = <CodegenCx<'ll, 'tcx> as BackendTypes>::DIScope;
|
||||
type DIVariable = <CodegenCx<'ll, 'tcx> as BackendTypes>::DIVariable;
|
||||
}
|
||||
|
||||
impl ty::layout::HasDataLayout for Builder<'_, '_, '_> {
|
||||
|
|
|
@ -91,6 +91,7 @@ impl BackendTypes for CodegenCx<'ll, 'tcx> {
|
|||
type Funclet = Funclet<'ll>;
|
||||
|
||||
type DIScope = &'ll llvm::debuginfo::DIScope;
|
||||
type DIVariable = &'ll llvm::debuginfo::DIVariable;
|
||||
}
|
||||
|
||||
impl CodegenCx<'ll, 'tcx> {
|
||||
|
|
|
@ -11,7 +11,7 @@ use self::utils::{create_DIArray, is_node_local_to_unit, span_start, DIB};
|
|||
|
||||
use crate::llvm;
|
||||
use crate::llvm::debuginfo::{
|
||||
DIArray, DIBuilder, DIFile, DIFlags, DILexicalBlock, DISPFlags, DIScope, DIType,
|
||||
DIArray, DIBuilder, DIFile, DIFlags, DILexicalBlock, DISPFlags, DIScope, DIType, DIVariable,
|
||||
};
|
||||
use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||
use rustc::ty::subst::{GenericArgKind, SubstsRef};
|
||||
|
@ -143,33 +143,23 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) {
|
|||
};
|
||||
}
|
||||
|
||||
impl DebugInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
|
||||
fn declare_local(
|
||||
impl DebugInfoBuilderMethods for Builder<'a, 'll, 'tcx> {
|
||||
// FIXME(eddyb) find a common convention for all of the debuginfo-related
|
||||
// names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.).
|
||||
fn dbg_var_addr(
|
||||
&mut self,
|
||||
dbg_context: &FunctionDebugContext<&'ll DIScope>,
|
||||
variable_name: ast::Name,
|
||||
variable_type: Ty<'tcx>,
|
||||
dbg_var: &'ll DIVariable,
|
||||
scope_metadata: &'ll DIScope,
|
||||
variable_alloca: Self::Value,
|
||||
direct_offset: Size,
|
||||
indirect_offsets: &[Size],
|
||||
variable_kind: VariableKind,
|
||||
span: Span,
|
||||
) {
|
||||
assert!(!dbg_context.source_locations_enabled);
|
||||
let cx = self.cx();
|
||||
|
||||
let file = span_start(cx, span).file;
|
||||
let file_metadata = file_metadata(cx, &file.name, dbg_context.defining_crate);
|
||||
|
||||
let loc = span_start(cx, span);
|
||||
let type_metadata = type_metadata(cx, variable_type, span);
|
||||
|
||||
let (argument_index, dwarf_tag) = match variable_kind {
|
||||
ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable),
|
||||
LocalVariable => (0, DW_TAG_auto_variable),
|
||||
};
|
||||
let align = cx.align_of(variable_type);
|
||||
|
||||
// Convert the direct and indirect offsets to address ops.
|
||||
let op_deref = || unsafe { llvm::LLVMRustDIBuilderCreateOpDeref() };
|
||||
|
@ -188,32 +178,19 @@ impl DebugInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
let name = SmallCStr::new(&variable_name.as_str());
|
||||
let metadata = unsafe {
|
||||
llvm::LLVMRustDIBuilderCreateVariable(
|
||||
DIB(cx),
|
||||
dwarf_tag,
|
||||
scope_metadata,
|
||||
name.as_ptr(),
|
||||
file_metadata,
|
||||
loc.line as c_uint,
|
||||
type_metadata,
|
||||
cx.sess().opts.optimize != config::OptLevel::No,
|
||||
DIFlags::FlagZero,
|
||||
argument_index,
|
||||
align.bytes() as u32,
|
||||
)
|
||||
};
|
||||
// FIXME(eddyb) maybe this information could be extracted from `var`,
|
||||
// to avoid having to pass it down in both places?
|
||||
source_loc::set_debug_location(
|
||||
self,
|
||||
InternalDebugLocation::new(scope_metadata, loc.line, loc.col.to_usize()),
|
||||
);
|
||||
unsafe {
|
||||
let debug_loc = llvm::LLVMGetCurrentDebugLocation(self.llbuilder);
|
||||
// FIXME(eddyb) replace `llvm.dbg.declare` with `llvm.dbg.addr`.
|
||||
let instr = llvm::LLVMRustDIBuilderInsertDeclareAtEnd(
|
||||
DIB(cx),
|
||||
variable_alloca,
|
||||
metadata,
|
||||
dbg_var,
|
||||
addr_ops.as_ptr(),
|
||||
addr_ops.len() as c_uint,
|
||||
debug_loc,
|
||||
|
@ -313,7 +290,8 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
// Get the linkage_name, which is just the symbol name
|
||||
let linkage_name = mangled_name_of_instance(self, instance);
|
||||
|
||||
let scope_line = span_start(self, span).line;
|
||||
// FIXME(eddyb) does this need to be separate from `loc.line` for some reason?
|
||||
let scope_line = loc.line;
|
||||
|
||||
let function_name = CString::new(name).unwrap();
|
||||
let linkage_name = SmallCStr::new(&linkage_name.name.as_str());
|
||||
|
@ -558,4 +536,44 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
fn debuginfo_finalize(&self) {
|
||||
finalize(self)
|
||||
}
|
||||
|
||||
// FIXME(eddyb) find a common convention for all of the debuginfo-related
|
||||
// names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.).
|
||||
fn create_dbg_var(
|
||||
&self,
|
||||
dbg_context: &FunctionDebugContext<&'ll DIScope>,
|
||||
variable_name: ast::Name,
|
||||
variable_type: Ty<'tcx>,
|
||||
scope_metadata: &'ll DIScope,
|
||||
variable_kind: VariableKind,
|
||||
span: Span,
|
||||
) -> &'ll DIVariable {
|
||||
let loc = span_start(self, span);
|
||||
let file_metadata = file_metadata(self, &loc.file.name, dbg_context.defining_crate);
|
||||
|
||||
let type_metadata = type_metadata(self, variable_type, span);
|
||||
|
||||
let (argument_index, dwarf_tag) = match variable_kind {
|
||||
ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable),
|
||||
LocalVariable => (0, DW_TAG_auto_variable),
|
||||
};
|
||||
let align = self.align_of(variable_type);
|
||||
|
||||
let name = SmallCStr::new(&variable_name.as_str());
|
||||
unsafe {
|
||||
llvm::LLVMRustDIBuilderCreateVariable(
|
||||
DIB(self),
|
||||
dwarf_tag,
|
||||
scope_metadata,
|
||||
name.as_ptr(),
|
||||
file_metadata,
|
||||
loc.line as c_uint,
|
||||
type_metadata,
|
||||
self.sess().opts.optimize != config::OptLevel::No,
|
||||
DIFlags::FlagZero,
|
||||
argument_index,
|
||||
align.bytes() as u32,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
use crate::traits::*;
|
||||
use rustc::mir;
|
||||
use rustc::session::config::DebugInfo;
|
||||
use rustc::ty;
|
||||
use rustc::ty::layout::{LayoutOf, Size};
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc_hir::def_id::CrateNum;
|
||||
use rustc_index::vec::IndexVec;
|
||||
|
||||
use rustc_span::symbol::kw;
|
||||
use rustc_span::symbol::{kw, Symbol};
|
||||
use rustc_span::{BytePos, Span};
|
||||
|
||||
use super::OperandValue;
|
||||
|
@ -24,6 +24,19 @@ pub enum VariableKind {
|
|||
LocalVariable,
|
||||
}
|
||||
|
||||
/// Like `mir::VarDebugInfo`, but within a `mir::Local`.
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct PerLocalVarDebugInfo<'tcx, D> {
|
||||
pub name: Symbol,
|
||||
pub source_info: mir::SourceInfo,
|
||||
|
||||
/// `DIVariable` returned by `create_dbg_var`.
|
||||
pub dbg_var: Option<D>,
|
||||
|
||||
/// `.place.projection` from `mir::VarDebugInfo`.
|
||||
pub projection: &'tcx ty::List<mir::PlaceElem<'tcx>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct DebugScope<D> {
|
||||
pub scope_metadata: Option<D>,
|
||||
|
@ -103,6 +116,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
// FIXME(eddyb) use `llvm.dbg.value` (which would work for operands),
|
||||
// not just `llvm.dbg.declare` (which requires `alloca`).
|
||||
pub fn debug_introduce_local(&self, bx: &mut Bx, local: mir::Local) {
|
||||
let full_debug_info = bx.sess().opts.debuginfo == DebugInfo::Full;
|
||||
|
||||
// FIXME(eddyb) maybe name the return place as `_0` or `return`?
|
||||
if local == mir::RETURN_PLACE {
|
||||
return;
|
||||
|
@ -112,35 +127,63 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
Some(per_local) => &per_local[local],
|
||||
None => return,
|
||||
};
|
||||
let whole_local_var = vars.iter().copied().find(|var| var.place.projection.is_empty());
|
||||
let has_proj = || vars.iter().any(|var| !var.place.projection.is_empty());
|
||||
let whole_local_var = vars.iter().find(|var| var.projection.is_empty()).copied();
|
||||
let has_proj = || vars.iter().any(|var| !var.projection.is_empty());
|
||||
|
||||
let (fallback_var, kind) = if self.mir.local_kind(local) == mir::LocalKind::Arg {
|
||||
let fallback_var = if self.mir.local_kind(local) == mir::LocalKind::Arg {
|
||||
let arg_index = local.index() - 1;
|
||||
|
||||
// Add debuginfo even to unnamed arguments.
|
||||
// FIXME(eddyb) is this really needed?
|
||||
let var = if arg_index == 0 && has_proj() {
|
||||
if arg_index == 0 && has_proj() {
|
||||
// Hide closure environments from debuginfo.
|
||||
// FIXME(eddyb) shouldn't `ArgumentVariable` indices
|
||||
// be offset to account for the hidden environment?
|
||||
None
|
||||
} else if whole_local_var.is_some() {
|
||||
// No need to make up anything, there is a `mir::VarDebugInfo`
|
||||
// covering the whole local.
|
||||
// FIXME(eddyb) take `whole_local_var.source_info.scope` into
|
||||
// account, just in case it doesn't use `ArgumentVariable`
|
||||
// (after #67586 gets fixed).
|
||||
None
|
||||
} else {
|
||||
Some(mir::VarDebugInfo {
|
||||
name: kw::Invalid,
|
||||
source_info: self.mir.local_decls[local].source_info,
|
||||
place: local.into(),
|
||||
})
|
||||
let name = kw::Invalid;
|
||||
let decl = &self.mir.local_decls[local];
|
||||
let (scope, span) = if full_debug_info {
|
||||
self.debug_loc(decl.source_info)
|
||||
} else {
|
||||
(None, decl.source_info.span)
|
||||
};
|
||||
(var, VariableKind::ArgumentVariable(arg_index + 1))
|
||||
let dbg_var = scope.map(|scope| {
|
||||
// FIXME(eddyb) is this `+ 1` needed at all?
|
||||
let kind = VariableKind::ArgumentVariable(arg_index + 1);
|
||||
|
||||
self.cx.create_dbg_var(
|
||||
self.debug_context.as_ref().unwrap(),
|
||||
name,
|
||||
self.monomorphize(&decl.ty),
|
||||
scope,
|
||||
kind,
|
||||
span,
|
||||
)
|
||||
});
|
||||
|
||||
Some(PerLocalVarDebugInfo {
|
||||
name,
|
||||
source_info: decl.source_info,
|
||||
dbg_var,
|
||||
projection: ty::List::empty(),
|
||||
})
|
||||
}
|
||||
} else {
|
||||
(None, VariableKind::LocalVariable)
|
||||
None
|
||||
};
|
||||
|
||||
let local_ref = &self.locals[local];
|
||||
|
||||
if !bx.sess().fewer_names() {
|
||||
let name = match whole_local_var.or(fallback_var.as_ref()) {
|
||||
let name = match whole_local_var.or(fallback_var) {
|
||||
Some(var) if var.name != kw::Invalid => var.name.to_string(),
|
||||
_ => format!("{:?}", local),
|
||||
};
|
||||
|
@ -163,7 +206,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
}
|
||||
}
|
||||
|
||||
if bx.sess().opts.debuginfo != DebugInfo::Full {
|
||||
if !full_debug_info {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -178,11 +221,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
_ => return,
|
||||
};
|
||||
|
||||
let vars = vars.iter().copied().chain(if whole_local_var.is_none() {
|
||||
fallback_var.as_ref()
|
||||
} else {
|
||||
None
|
||||
});
|
||||
let vars = vars.iter().copied().chain(fallback_var);
|
||||
|
||||
for var in vars {
|
||||
let mut layout = base.layout;
|
||||
|
@ -190,10 +229,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
// FIXME(eddyb) use smallvec here.
|
||||
let mut indirect_offsets = vec![];
|
||||
|
||||
let kind =
|
||||
if var.place.projection.is_empty() { kind } else { VariableKind::LocalVariable };
|
||||
|
||||
for elem in &var.place.projection[..] {
|
||||
for elem in &var.projection[..] {
|
||||
match *elem {
|
||||
mir::ProjectionElem::Deref => {
|
||||
indirect_offsets.push(Size::ZERO);
|
||||
|
@ -202,7 +238,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
.ty
|
||||
.builtin_deref(true)
|
||||
.unwrap_or_else(|| {
|
||||
span_bug!(var.source_info.span, "cannot deref `{}`", layout.ty,)
|
||||
span_bug!(var.source_info.span, "cannot deref `{}`", layout.ty)
|
||||
})
|
||||
.ty,
|
||||
);
|
||||
|
@ -219,27 +255,27 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
_ => span_bug!(
|
||||
var.source_info.span,
|
||||
"unsupported var debuginfo place `{:?}`",
|
||||
var.place,
|
||||
mir::Place { local, projection: var.projection },
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
let (scope, span) = self.debug_loc(var.source_info);
|
||||
if let Some(scope) = scope {
|
||||
bx.declare_local(
|
||||
if let Some(dbg_var) = var.dbg_var {
|
||||
bx.dbg_var_addr(
|
||||
debug_context,
|
||||
var.name,
|
||||
layout.ty,
|
||||
dbg_var,
|
||||
scope,
|
||||
base.llval,
|
||||
direct_offset,
|
||||
&indirect_offsets,
|
||||
kind,
|
||||
span,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn debug_introduce_locals(&self, bx: &mut Bx) {
|
||||
if bx.sess().opts.debuginfo == DebugInfo::Full || !bx.sess().fewer_names() {
|
||||
|
@ -248,20 +284,60 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Partition all `VarDebugInfo` in `self.mir`, by their base `Local`.
|
||||
pub fn compute_per_local_var_debug_info(
|
||||
&self,
|
||||
) -> Option<IndexVec<mir::Local, Vec<PerLocalVarDebugInfo<'tcx, Bx::DIVariable>>>> {
|
||||
let full_debug_info = self.cx.sess().opts.debuginfo == DebugInfo::Full;
|
||||
|
||||
if !(full_debug_info || !self.cx.sess().fewer_names()) {
|
||||
return None;
|
||||
}
|
||||
|
||||
/// Partition all `VarDebuginfo` in `body`, by their base `Local`.
|
||||
pub fn per_local_var_debug_info(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &'a mir::Body<'tcx>,
|
||||
) -> Option<IndexVec<mir::Local, Vec<&'a mir::VarDebugInfo<'tcx>>>> {
|
||||
if tcx.sess.opts.debuginfo == DebugInfo::Full || !tcx.sess.fewer_names() {
|
||||
let mut per_local = IndexVec::from_elem(vec![], &body.local_decls);
|
||||
for var in &body.var_debug_info {
|
||||
per_local[var.place.local].push(var);
|
||||
let mut per_local = IndexVec::from_elem(vec![], &self.mir.local_decls);
|
||||
for var in &self.mir.var_debug_info {
|
||||
let (scope, span) = if full_debug_info {
|
||||
self.debug_loc(var.source_info)
|
||||
} else {
|
||||
(None, var.source_info.span)
|
||||
};
|
||||
let dbg_var = scope.map(|scope| {
|
||||
let place = var.place;
|
||||
let var_ty = self.monomorphized_place_ty(place.as_ref());
|
||||
let var_kind = if self.mir.local_kind(place.local) == mir::LocalKind::Arg
|
||||
&& place.projection.is_empty()
|
||||
{
|
||||
// FIXME(eddyb, #67586) take `var.source_info.scope` into
|
||||
// account to avoid using `ArgumentVariable` more than once
|
||||
// per argument local.
|
||||
|
||||
let arg_index = place.local.index() - 1;
|
||||
|
||||
// FIXME(eddyb) shouldn't `ArgumentVariable` indices be
|
||||
// offset in closures to account for the hidden environment?
|
||||
// Also, is this `+ 1` needed at all?
|
||||
VariableKind::ArgumentVariable(arg_index + 1)
|
||||
} else {
|
||||
VariableKind::LocalVariable
|
||||
};
|
||||
self.cx.create_dbg_var(
|
||||
self.debug_context.as_ref().unwrap(),
|
||||
var.name,
|
||||
var_ty,
|
||||
scope,
|
||||
var_kind,
|
||||
span,
|
||||
)
|
||||
});
|
||||
|
||||
per_local[var.place.local].push(PerLocalVarDebugInfo {
|
||||
name: var.name,
|
||||
source_info: var.source_info,
|
||||
dbg_var,
|
||||
projection: var.place.projection,
|
||||
});
|
||||
}
|
||||
Some(per_local)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ use rustc_index::bit_set::BitSet;
|
|||
use rustc_index::vec::IndexVec;
|
||||
|
||||
use self::analyze::CleanupKind;
|
||||
use self::debuginfo::FunctionDebugContext;
|
||||
use self::debuginfo::{FunctionDebugContext, PerLocalVarDebugInfo};
|
||||
use self::place::PlaceRef;
|
||||
use rustc::mir::traversal;
|
||||
|
||||
|
@ -74,9 +74,10 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
|
|||
/// notably `expect`.
|
||||
locals: IndexVec<mir::Local, LocalRef<'tcx, Bx::Value>>,
|
||||
|
||||
/// All `VarDebuginfo` from the MIR body, partitioned by `Local`.
|
||||
/// This is `None` if no variable debuginfo/names are needed.
|
||||
per_local_var_debug_info: Option<IndexVec<mir::Local, Vec<&'tcx mir::VarDebugInfo<'tcx>>>>,
|
||||
/// All `VarDebugInfo` from the MIR body, partitioned by `Local`.
|
||||
/// This is `None` if no var`#[non_exhaustive]`iable debuginfo/names are needed.
|
||||
per_local_var_debug_info:
|
||||
Option<IndexVec<mir::Local, Vec<PerLocalVarDebugInfo<'tcx, Bx::DIVariable>>>>,
|
||||
|
||||
/// Caller location propagated if this function has `#[track_caller]`.
|
||||
caller_location: Option<OperandRef<'tcx, Bx::Value>>,
|
||||
|
@ -178,10 +179,12 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
funclets,
|
||||
locals: IndexVec::new(),
|
||||
debug_context,
|
||||
per_local_var_debug_info: debuginfo::per_local_var_debug_info(cx.tcx(), mir_body),
|
||||
per_local_var_debug_info: None,
|
||||
caller_location: None,
|
||||
};
|
||||
|
||||
fx.per_local_var_debug_info = fx.compute_per_local_var_debug_info();
|
||||
|
||||
let memory_locals = analyze::non_ssa_locals(&fx);
|
||||
|
||||
// Allocate variable and temp allocas
|
||||
|
|
|
@ -21,7 +21,10 @@ pub trait BackendTypes {
|
|||
type Type: CodegenObject;
|
||||
type Funclet;
|
||||
|
||||
// FIXME(eddyb) find a common convention for all of the debuginfo-related
|
||||
// names (choose between `Dbg`, `Debug`, `DebugInfo`, `DI` etc.).
|
||||
type DIScope: Copy;
|
||||
type DIVariable: Copy;
|
||||
}
|
||||
|
||||
pub trait Backend<'tcx>:
|
||||
|
|
|
@ -28,7 +28,7 @@ pub enum OverflowOp {
|
|||
|
||||
pub trait BuilderMethods<'a, 'tcx>:
|
||||
HasCodegen<'tcx>
|
||||
+ DebugInfoBuilderMethods<'tcx>
|
||||
+ DebugInfoBuilderMethods
|
||||
+ ArgAbiMethods<'tcx>
|
||||
+ AbiBuilderMethods<'tcx>
|
||||
+ IntrinsicCallMethods<'tcx>
|
||||
|
|
|
@ -30,20 +30,32 @@ pub trait DebugInfoMethods<'tcx>: BackendTypes {
|
|||
defining_crate: CrateNum,
|
||||
) -> Self::DIScope;
|
||||
fn debuginfo_finalize(&self);
|
||||
}
|
||||
|
||||
pub trait DebugInfoBuilderMethods<'tcx>: BackendTypes {
|
||||
fn declare_local(
|
||||
&mut self,
|
||||
// FIXME(eddyb) find a common convention for all of the debuginfo-related
|
||||
// names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.).
|
||||
fn create_dbg_var(
|
||||
&self,
|
||||
dbg_context: &FunctionDebugContext<Self::DIScope>,
|
||||
variable_name: Name,
|
||||
variable_type: Ty<'tcx>,
|
||||
scope_metadata: Self::DIScope,
|
||||
variable_kind: VariableKind,
|
||||
span: Span,
|
||||
) -> Self::DIVariable;
|
||||
}
|
||||
|
||||
pub trait DebugInfoBuilderMethods: BackendTypes {
|
||||
// FIXME(eddyb) find a common convention for all of the debuginfo-related
|
||||
// names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.).
|
||||
fn dbg_var_addr(
|
||||
&mut self,
|
||||
dbg_context: &FunctionDebugContext<Self::DIScope>,
|
||||
dbg_var: Self::DIVariable,
|
||||
scope_metadata: Self::DIScope,
|
||||
variable_alloca: Self::Value,
|
||||
direct_offset: Size,
|
||||
// NB: each offset implies a deref (i.e. they're steps in a pointer chain).
|
||||
indirect_offsets: &[Size],
|
||||
variable_kind: VariableKind,
|
||||
span: Span,
|
||||
);
|
||||
fn set_source_location(
|
||||
|
|
|
@ -93,5 +93,6 @@ pub trait HasCodegen<'tcx>:
|
|||
Type = Self::Type,
|
||||
Funclet = Self::Funclet,
|
||||
DIScope = Self::DIScope,
|
||||
DIVariable = Self::DIVariable,
|
||||
>;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue