]> git.proxmox.com Git - rustc.git/blame - src/librustc_codegen_llvm/debuginfo/type_names.rs
New upstream version 1.29.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};
d9579d0f 17
54a0048b 18use rustc::hir;
d9579d0f
AL
19
20// Compute the name of the type as it should be stored in debuginfo. Does not do
21// any caching, i.e. calling the function twice with the same type will also do
22// the work twice. The `qualified` parameter only affects the first level of the
23// type name, further levels (i.e. type parameters) are always fully qualified.
2c00a5a8 24pub fn compute_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
d9579d0f
AL
25 t: Ty<'tcx>,
26 qualified: bool)
27 -> String {
28 let mut result = String::with_capacity(64);
29 push_debuginfo_type_name(cx, t, qualified, &mut result);
30 result
31}
32
33// Pushes the name of the type as it should be stored in debuginfo on the
34// `output` String. See also compute_debuginfo_type_name().
2c00a5a8 35pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
d9579d0f
AL
36 t: Ty<'tcx>,
37 qualified: bool,
38 output: &mut String) {
3b2f2976
XL
39 // When targeting MSVC, emit C++ style type names for compatibility with
40 // .natvis visualizers (and perhaps other existing native debuggers?)
41 let cpp_like_names = cx.sess().target.target.options.is_like_msvc;
42
d9579d0f 43 match t.sty {
92a42be0
SL
44 ty::TyBool => output.push_str("bool"),
45 ty::TyChar => output.push_str("char"),
46 ty::TyStr => output.push_str("str"),
5bcae85e 47 ty::TyNever => output.push_str("!"),
9cc50fc6
SL
48 ty::TyInt(int_ty) => output.push_str(int_ty.ty_to_string()),
49 ty::TyUint(uint_ty) => output.push_str(uint_ty.ty_to_string()),
50 ty::TyFloat(float_ty) => output.push_str(float_ty.ty_to_string()),
abe05a73 51 ty::TyForeign(def_id) => push_item_name(cx, def_id, qualified, output),
9e0c209e 52 ty::TyAdt(def, substs) => {
e9174d1e 53 push_item_name(cx, def.did, qualified, output);
d9579d0f
AL
54 push_type_params(cx, substs, output);
55 },
0531ce1d 56 ty::TyTuple(component_types) => {
d9579d0f
AL
57 output.push('(');
58 for &component_type in component_types {
59 push_debuginfo_type_name(cx, component_type, true, output);
60 output.push_str(", ");
61 }
62 if !component_types.is_empty() {
63 output.pop();
64 output.pop();
65 }
66 output.push(')');
67 },
c1a9b12d 68 ty::TyRawPtr(ty::TypeAndMut { ty: inner_type, mutbl } ) => {
3b2f2976
XL
69 if !cpp_like_names {
70 output.push('*');
71 }
d9579d0f 72 match mutbl {
e9174d1e
SL
73 hir::MutImmutable => output.push_str("const "),
74 hir::MutMutable => output.push_str("mut "),
d9579d0f
AL
75 }
76
77 push_debuginfo_type_name(cx, inner_type, true, output);
3b2f2976
XL
78
79 if cpp_like_names {
80 output.push('*');
81 }
d9579d0f 82 },
94b46f34 83 ty::TyRef(_, inner_type, mutbl) => {
3b2f2976
XL
84 if !cpp_like_names {
85 output.push('&');
86 }
e9174d1e 87 if mutbl == hir::MutMutable {
d9579d0f
AL
88 output.push_str("mut ");
89 }
90
91 push_debuginfo_type_name(cx, inner_type, true, output);
3b2f2976
XL
92
93 if cpp_like_names {
94 output.push('*');
95 }
d9579d0f 96 },
62682a34
SL
97 ty::TyArray(inner_type, len) => {
98 output.push('[');
99 push_debuginfo_type_name(cx, inner_type, true, output);
94b46f34 100 output.push_str(&format!("; {}", len.unwrap_usize(cx.tcx)));
62682a34
SL
101 output.push(']');
102 },
103 ty::TySlice(inner_type) => {
3b2f2976
XL
104 if cpp_like_names {
105 output.push_str("slice<");
106 } else {
107 output.push('[');
108 }
109
d9579d0f 110 push_debuginfo_type_name(cx, inner_type, true, output);
3b2f2976
XL
111
112 if cpp_like_names {
113 output.push('>');
114 } else {
115 output.push(']');
116 }
d9579d0f 117 },
476ff2be
SL
118 ty::TyDynamic(ref trait_data, ..) => {
119 if let Some(principal) = trait_data.principal() {
0531ce1d
XL
120 let principal = cx.tcx.normalize_erasing_late_bound_regions(
121 ty::ParamEnv::reveal_all(),
122 &principal,
123 );
476ff2be
SL
124 push_item_name(cx, principal.def_id, false, output);
125 push_type_params(cx, principal.substs, output);
126 }
d9579d0f 127 },
041b39d2 128 ty::TyFnDef(..) | ty::TyFnPtr(_) => {
2c00a5a8 129 let sig = t.fn_sig(cx.tcx);
8bb4bdeb 130 if sig.unsafety() == hir::Unsafety::Unsafe {
d9579d0f
AL
131 output.push_str("unsafe ");
132 }
133
8bb4bdeb 134 let abi = sig.abi();
54a0048b 135 if abi != ::abi::Abi::Rust {
d9579d0f
AL
136 output.push_str("extern \"");
137 output.push_str(abi.name());
138 output.push_str("\" ");
139 }
140
141 output.push_str("fn(");
142
0531ce1d 143 let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
476ff2be
SL
144 if !sig.inputs().is_empty() {
145 for &parameter_type in sig.inputs() {
d9579d0f
AL
146 push_debuginfo_type_name(cx, parameter_type, true, output);
147 output.push_str(", ");
148 }
149 output.pop();
150 output.pop();
151 }
152
153 if sig.variadic {
476ff2be 154 if !sig.inputs().is_empty() {
d9579d0f
AL
155 output.push_str(", ...");
156 } else {
157 output.push_str("...");
158 }
159 }
160
161 output.push(')');
162
476ff2be 163 if !sig.output().is_nil() {
5bcae85e 164 output.push_str(" -> ");
476ff2be 165 push_debuginfo_type_name(cx, sig.output(), true, output);
d9579d0f
AL
166 }
167 },
62682a34 168 ty::TyClosure(..) => {
d9579d0f
AL
169 output.push_str("closure");
170 }
ea8adc8c
XL
171 ty::TyGenerator(..) => {
172 output.push_str("generator");
173 }
62682a34
SL
174 ty::TyError |
175 ty::TyInfer(_) |
176 ty::TyProjection(..) |
5bcae85e 177 ty::TyAnon(..) |
2c00a5a8 178 ty::TyGeneratorWitness(..) |
62682a34 179 ty::TyParam(_) => {
54a0048b
SL
180 bug!("debuginfo: Trying to create type name for \
181 unexpected type: {:?}", t);
d9579d0f
AL
182 }
183 }
184
2c00a5a8 185 fn push_item_name(cx: &CodegenCx,
e9174d1e 186 def_id: DefId,
d9579d0f
AL
187 qualified: bool,
188 output: &mut String) {
54a0048b 189 if qualified {
2c00a5a8
XL
190 output.push_str(&cx.tcx.crate_name(def_id.krate).as_str());
191 for path_element in cx.tcx.def_path(def_id).data {
54a0048b 192 output.push_str("::");
83c7162d 193 output.push_str(&path_element.data.as_interned_str().as_str());
d9579d0f 194 }
54a0048b 195 } else {
83c7162d 196 output.push_str(&cx.tcx.item_name(def_id).as_str());
54a0048b 197 }
d9579d0f
AL
198 }
199
200 // Pushes the type parameters in the given `Substs` to the output string.
201 // This ignores region parameters, since they can't reliably be
202 // reconstructed for items from non-local crates. For local crates, this
203 // would be possible but with inlining and LTO we have to use the least
204 // common denominator - otherwise we would run into conflicts.
2c00a5a8 205 fn push_type_params<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
9e0c209e 206 substs: &Substs<'tcx>,
d9579d0f 207 output: &mut String) {
9e0c209e 208 if substs.types().next().is_none() {
d9579d0f
AL
209 return;
210 }
211
212 output.push('<');
213
9e0c209e 214 for type_parameter in substs.types() {
d9579d0f
AL
215 push_debuginfo_type_name(cx, type_parameter, true, output);
216 output.push_str(", ");
217 }
218
219 output.pop();
220 output.pop();
221
222 output.push('>');
223 }
224}