]> git.proxmox.com Git - rustc.git/blame - src/librustc_codegen_llvm/debuginfo/type_names.rs
New upstream version 1.32.0+dfsg1
[rustc.git] / src / librustc_codegen_llvm / debuginfo / type_names.rs
CommitLineData
d9579d0f
AL
1// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11// Type Names for Debug Info.
12
2c00a5a8 13use common::CodegenCx;
54a0048b 14use rustc::hir::def_id::DefId;
9e0c209e 15use rustc::ty::subst::Substs;
54a0048b 16use rustc::ty::{self, Ty};
a1dfa0c6 17use rustc_codegen_ssa::traits::*;
d9579d0f 18
54a0048b 19use rustc::hir;
d9579d0f
AL
20
21// Compute the name of the type as it should be stored in debuginfo. Does not do
22// any caching, i.e. calling the function twice with the same type will also do
23// the work twice. The `qualified` parameter only affects the first level of the
24// type name, further levels (i.e. type parameters) are always fully qualified.
2c00a5a8 25pub fn compute_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
d9579d0f
AL
26 t: Ty<'tcx>,
27 qualified: bool)
28 -> String {
29 let mut result = String::with_capacity(64);
30 push_debuginfo_type_name(cx, t, qualified, &mut result);
31 result
32}
33
34// Pushes the name of the type as it should be stored in debuginfo on the
35// `output` String. See also compute_debuginfo_type_name().
2c00a5a8 36pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
d9579d0f
AL
37 t: Ty<'tcx>,
38 qualified: bool,
39 output: &mut String) {
3b2f2976
XL
40 // When targeting MSVC, emit C++ style type names for compatibility with
41 // .natvis visualizers (and perhaps other existing native debuggers?)
42 let cpp_like_names = cx.sess().target.target.options.is_like_msvc;
43
d9579d0f 44 match t.sty {
b7449926
XL
45 ty::Bool => output.push_str("bool"),
46 ty::Char => output.push_str("char"),
47 ty::Str => output.push_str("str"),
48 ty::Never => output.push_str("!"),
49 ty::Int(int_ty) => output.push_str(int_ty.ty_to_string()),
50 ty::Uint(uint_ty) => output.push_str(uint_ty.ty_to_string()),
51 ty::Float(float_ty) => output.push_str(float_ty.ty_to_string()),
52 ty::Foreign(def_id) => push_item_name(cx, def_id, qualified, output),
53 ty::Adt(def, substs) => {
e9174d1e 54 push_item_name(cx, def.did, qualified, output);
d9579d0f
AL
55 push_type_params(cx, substs, output);
56 },
b7449926 57 ty::Tuple(component_types) => {
d9579d0f
AL
58 output.push('(');
59 for &component_type in component_types {
60 push_debuginfo_type_name(cx, component_type, true, output);
61 output.push_str(", ");
62 }
63 if !component_types.is_empty() {
64 output.pop();
65 output.pop();
66 }
67 output.push(')');
68 },
b7449926 69 ty::RawPtr(ty::TypeAndMut { ty: inner_type, mutbl } ) => {
3b2f2976
XL
70 if !cpp_like_names {
71 output.push('*');
72 }
d9579d0f 73 match mutbl {
e9174d1e
SL
74 hir::MutImmutable => output.push_str("const "),
75 hir::MutMutable => output.push_str("mut "),
d9579d0f
AL
76 }
77
78 push_debuginfo_type_name(cx, inner_type, true, output);
3b2f2976
XL
79
80 if cpp_like_names {
81 output.push('*');
82 }
d9579d0f 83 },
b7449926 84 ty::Ref(_, inner_type, mutbl) => {
3b2f2976
XL
85 if !cpp_like_names {
86 output.push('&');
87 }
e9174d1e 88 if mutbl == hir::MutMutable {
d9579d0f
AL
89 output.push_str("mut ");
90 }
91
92 push_debuginfo_type_name(cx, inner_type, true, output);
3b2f2976
XL
93
94 if cpp_like_names {
95 output.push('*');
96 }
d9579d0f 97 },
b7449926 98 ty::Array(inner_type, len) => {
62682a34
SL
99 output.push('[');
100 push_debuginfo_type_name(cx, inner_type, true, output);
94b46f34 101 output.push_str(&format!("; {}", len.unwrap_usize(cx.tcx)));
62682a34
SL
102 output.push(']');
103 },
b7449926 104 ty::Slice(inner_type) => {
3b2f2976
XL
105 if cpp_like_names {
106 output.push_str("slice<");
107 } else {
108 output.push('[');
109 }
110
d9579d0f 111 push_debuginfo_type_name(cx, inner_type, true, output);
3b2f2976
XL
112
113 if cpp_like_names {
114 output.push('>');
115 } else {
116 output.push(']');
117 }
d9579d0f 118 },
b7449926 119 ty::Dynamic(ref trait_data, ..) => {
0bf4aa26
XL
120 let principal = cx.tcx.normalize_erasing_late_bound_regions(
121 ty::ParamEnv::reveal_all(),
122 &trait_data.principal(),
123 );
124 push_item_name(cx, principal.def_id, false, output);
125 push_type_params(cx, principal.substs, output);
d9579d0f 126 },
b7449926 127 ty::FnDef(..) | ty::FnPtr(_) => {
2c00a5a8 128 let sig = t.fn_sig(cx.tcx);
8bb4bdeb 129 if sig.unsafety() == hir::Unsafety::Unsafe {
d9579d0f
AL
130 output.push_str("unsafe ");
131 }
132
8bb4bdeb 133 let abi = sig.abi();
54a0048b 134 if abi != ::abi::Abi::Rust {
d9579d0f
AL
135 output.push_str("extern \"");
136 output.push_str(abi.name());
137 output.push_str("\" ");
138 }
139
140 output.push_str("fn(");
141
0531ce1d 142 let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
476ff2be
SL
143 if !sig.inputs().is_empty() {
144 for &parameter_type in sig.inputs() {
d9579d0f
AL
145 push_debuginfo_type_name(cx, parameter_type, true, output);
146 output.push_str(", ");
147 }
148 output.pop();
149 output.pop();
150 }
151
152 if sig.variadic {
476ff2be 153 if !sig.inputs().is_empty() {
d9579d0f
AL
154 output.push_str(", ...");
155 } else {
156 output.push_str("...");
157 }
158 }
159
160 output.push(')');
161
b7449926 162 if !sig.output().is_unit() {
5bcae85e 163 output.push_str(" -> ");
476ff2be 164 push_debuginfo_type_name(cx, sig.output(), true, output);
d9579d0f
AL
165 }
166 },
b7449926 167 ty::Closure(..) => {
d9579d0f
AL
168 output.push_str("closure");
169 }
b7449926 170 ty::Generator(..) => {
ea8adc8c
XL
171 output.push_str("generator");
172 }
b7449926
XL
173 ty::Error |
174 ty::Infer(_) |
a1dfa0c6 175 ty::Placeholder(..) |
0bf4aa26 176 ty::UnnormalizedProjection(..) |
b7449926 177 ty::Projection(..) |
a1dfa0c6 178 ty::Bound(..) |
b7449926
XL
179 ty::Opaque(..) |
180 ty::GeneratorWitness(..) |
181 ty::Param(_) => {
54a0048b 182 bug!("debuginfo: Trying to create type name for \
0bf4aa26 183 unexpected type: {:?}", t);
d9579d0f
AL
184 }
185 }
186
2c00a5a8 187 fn push_item_name(cx: &CodegenCx,
e9174d1e 188 def_id: DefId,
d9579d0f
AL
189 qualified: bool,
190 output: &mut String) {
54a0048b 191 if qualified {
2c00a5a8
XL
192 output.push_str(&cx.tcx.crate_name(def_id.krate).as_str());
193 for path_element in cx.tcx.def_path(def_id).data {
54a0048b 194 output.push_str("::");
83c7162d 195 output.push_str(&path_element.data.as_interned_str().as_str());
d9579d0f 196 }
54a0048b 197 } else {
83c7162d 198 output.push_str(&cx.tcx.item_name(def_id).as_str());
54a0048b 199 }
d9579d0f
AL
200 }
201
202 // Pushes the type parameters in the given `Substs` to the output string.
203 // This ignores region parameters, since they can't reliably be
204 // reconstructed for items from non-local crates. For local crates, this
205 // would be possible but with inlining and LTO we have to use the least
206 // common denominator - otherwise we would run into conflicts.
2c00a5a8 207 fn push_type_params<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
9e0c209e 208 substs: &Substs<'tcx>,
d9579d0f 209 output: &mut String) {
9e0c209e 210 if substs.types().next().is_none() {
d9579d0f
AL
211 return;
212 }
213
214 output.push('<');
215
9e0c209e 216 for type_parameter in substs.types() {
d9579d0f
AL
217 push_debuginfo_type_name(cx, type_parameter, true, output);
218 output.push_str(", ");
219 }
220
221 output.pop();
222 output.pop();
223
224 output.push('>');
225 }
226}