111
|
1 // names.cc -- Names used by gofrontend generated code.
|
|
2
|
|
3 // Copyright 2017 The Go Authors. All rights reserved.
|
|
4 // Use of this source code is governed by a BSD-style
|
|
5 // license that can be found in the LICENSE file.
|
|
6
|
|
7 #include "go-system.h"
|
|
8
|
|
9 #include "gogo.h"
|
|
10 #include "go-encode-id.h"
|
|
11 #include "types.h"
|
|
12 #include "expressions.h"
|
|
13
|
|
14 // This file contains functions that generate names that appear in the
|
|
15 // assembly code. This is not used for names that appear only in the
|
|
16 // debug info.
|
|
17
|
131
|
18 // Our external names contain only ASCII alphanumeric characters,
|
|
19 // underscore, and dot. (According to the GCC sources, dot is not
|
|
20 // permitted in assembler symbols on VxWorks and MMIX. We will not
|
|
21 // support those systems.) Go names can not contain dot, so we rely
|
|
22 // on using dot to encode Unicode characters, and to separate Go
|
|
23 // symbols by package, and so forth. We assume that none of the
|
|
24 // non-Go symbols in the final link will contain a dot, so we don't
|
|
25 // worry about conflicts.
|
|
26 //
|
|
27 // We first describe the basic symbol names, used to represent Go
|
|
28 // functions and variables. These never start with a dot, never end
|
|
29 // with a dot, never contain two consecutive dots, and never contain a
|
|
30 // dot followed by a digit.
|
|
31 //
|
|
32 // The external name for a normal Go symbol NAME, a function or
|
|
33 // variable, is simply "PKGPATH.NAME". Note that NAME is not the
|
|
34 // packed form used for the "hidden" name internally in the compiler;
|
|
35 // it is the name that appears in the source code. PKGPATH is the
|
145
|
36 // -fgo-pkgpath option as adjusted by Gogo::pkgpath_for_symbol. Note
|
131
|
37 // that PKGPATH can not contain a dot and neither can NAME. Also,
|
|
38 // NAME may not begin with a digit. NAME may require further encoding
|
|
39 // for non-ASCII characters as described below, but until that
|
|
40 // encoding these symbols contain exactly one dot, and they do not
|
|
41 // start with a dot.
|
|
42 //
|
|
43 // The external name for a method NAME for a named type TYPE is
|
|
44 // "PKGPATH.TYPE.NAME". Unlike the gc compiler, the external name
|
|
45 // does not indicate whether this is a pointer method or a value
|
|
46 // method; a named type can not have both a pointer and value method
|
|
47 // with the same name, so there is no ambiguity. PKGPATH is the
|
|
48 // package path of the package in which TYPE is defined. Here none of
|
|
49 // PKGPATH, TYPE, or NAME can be empty or contain a dot, and neither
|
|
50 // TYPE nor NAME may begin with a digit. Before encoding these names
|
|
51 // contain exactly two dots, not consecutive, and they do not start
|
|
52 // with a dot.
|
|
53 //
|
|
54 // It's uncommon, but the use of type literals with embedded fields
|
|
55 // can cause us to have methods on unnamed types. The external names
|
|
56 // for these are also PKGPATH.TYPE.NAME, where TYPE is an
|
|
57 // approximately readable version of the type literal, described
|
|
58 // below. As the type literal encoding always contains multiple dots,
|
|
59 // these names always contain more than two dots. Although the type
|
|
60 // literal encoding contains dots, neither PKGPATH nor NAME can
|
|
61 // contain a dot, and neither TYPE nor NAME can begin with a digit.
|
|
62 // The effect is that PKGPATH is always the portion of the name before
|
|
63 // the first dot and NAME is always the portion after the last dot.
|
|
64 // There is no ambiguity as long as encoded type literals are
|
|
65 // unambiguous.
|
|
66 //
|
|
67 // Also uncommon is an external name that must refer to a named type
|
|
68 // defined within a function. While such a type can not have methods
|
|
69 // itself, it can pick up embedded methods, and those methods need
|
|
70 // names. These are treated as a kind of type literal written as,
|
|
71 // before type literal encoding, FNNAME.TYPENAME(INDEX) or, for a
|
|
72 // method, TYPE.MNAME.TYPENAME(INDEX). INDEX is the index of that
|
|
73 // named type within the function, as a single function can have
|
|
74 // multiple types with the same name. This is unambiguous as
|
|
75 // parentheses can not appear in a type literal in this form (they can
|
|
76 // only appear in interface method declarations).
|
|
77 //
|
|
78 // That is the end of the list of basic names. The remaining names
|
|
79 // exist for special purposes, and are differentiated from the basic
|
|
80 // names by containing two consecutive dots.
|
|
81 //
|
|
82 // The hash function for a type is treated as a method whose name is
|
|
83 // ".hash". That is, the method name begins with a dot. The effect
|
|
84 // is that there will be two consecutive dots in the name; the name
|
|
85 // will always end with "..hash".
|
|
86 //
|
|
87 // Similarly the equality function for a type is treated as a method
|
|
88 // whose name is ".eq".
|
|
89 //
|
|
90 // The function descriptor for a function is the same as the name of
|
|
91 // the function with an added suffix "..f".
|
|
92 //
|
|
93 // A thunk for a go or defer statement is treated as a function whose
|
|
94 // name is ".thunkNN" where NN is a sequence of digits (these
|
|
95 // functions are never globally visible). Thus the final name of a
|
|
96 // thunk will be PKGPATH..thunkNN.
|
|
97 //
|
|
98 // An init function is treated as a function whose name is ".initNN"
|
|
99 // where NN is a sequence of digits (these functions are never
|
|
100 // globally visible). Thus the final name of an init function will be
|
|
101 // PKGPATH..initNN.
|
|
102 //
|
|
103 // A nested function is given the name of outermost enclosing function
|
|
104 // or method with an added suffix "..funcNN" where NN is a sequence of
|
|
105 // digits. Note that the function descriptor of a nested function, if
|
|
106 // needed, will end with "..funcNN..f".
|
|
107 //
|
|
108 // A recover thunk is the same as the name of the function with an
|
|
109 // added suffix "..r".
|
|
110 //
|
|
111 // The name of a type descriptor for a named type is PKGPATH.TYPE..d.
|
|
112 //
|
|
113 // The name of a type descriptor for an unnamed type is type..TYPE.
|
|
114 // That is, the string "type.." followed by the type literal encoding.
|
|
115 // These names are common symbols, in the linker's sense of the word
|
|
116 // common: in the final executable there is only one instance of the
|
|
117 // type descriptor for a given unnamed type. The type literal
|
|
118 // encoding can never start with a digit or with 'u' or 'U'.
|
|
119 //
|
|
120 // The name of the GC symbol for a named type is PKGPATH.TYPE..g.
|
|
121 //
|
|
122 // The name of the GC symbol for an unnamed type is typeg..TYPE.
|
|
123 // These are common symbols.
|
|
124 //
|
|
125 // The name of a ptrmask symbol is gcbits..B32 where B32 is an
|
|
126 // encoding of the ptrmask bits using only ASCII letters without 'u'
|
|
127 // or 'U'. These are common symbols.
|
|
128 //
|
|
129 // An interface method table for assigning the non-interface type TYPE
|
|
130 // to the interface type ITYPE is named imt..ITYPE..TYPE. If ITYPE or
|
|
131 // TYPE is a named type, they are written as PKGPATH.TYPE. Otherwise
|
|
132 // they are written as a type literal. An interface method table for
|
|
133 // a pointer method set uses pimt instead of imt.
|
|
134 //
|
|
135 // The names of composite literal initializers, including the GC root
|
|
136 // variable, are not referenced. They must not conflict with any C
|
|
137 // language names, but the names are otherwise unimportant. They are
|
|
138 // named "go..CNN" where NN is a sequence of digits. The names do not
|
|
139 // include the PKGPATH.
|
|
140 //
|
|
141 // The map zero value, a common symbol that represents the zero value
|
|
142 // of a map, is named simply "go..zerovalue". The name does not
|
|
143 // include the PKGPATH.
|
|
144 //
|
|
145 // The import function for the main package is referenced by C code,
|
|
146 // and is named __go_init_main. For other packages it is
|
145
|
147 // PKGPATH..import. If a package doesn't need an init function, it
|
|
148 // will have a dummy one, named ~PKGPATH.
|
|
149 //
|
|
150 // In each pacakge there is a list of all the type descriptors defined
|
|
151 // in this package. The name of the list is PKGPATH..types.
|
|
152 //
|
|
153 // In the main package it gathers all the type descriptor lists in a
|
|
154 // single list, named go..typelists.
|
131
|
155 //
|
|
156 // The type literal encoding is essentially a single line version of
|
|
157 // the type literal, such as "struct { pkgpath.i int; J int }". In
|
|
158 // this representation unexported names use their pkgpath, exported
|
|
159 // names omit it.
|
|
160 //
|
|
161 // The type literal encoding is not quite valid Go, as some aspects of
|
|
162 // compiler generated types can not be represented. For example,
|
|
163 // incomparable struct types have an extra field "{x}". Struct tags
|
|
164 // are quoted inside curly braces, rather than introduce an encoding
|
|
165 // for quotes. Struct tags can contain any character, so any single
|
|
166 // byte Unicode character that is not alphanumeric or underscore is
|
|
167 // replaced with .xNN where NN is the hex encoding.
|
|
168 //
|
|
169 // There is a simple encoding for glue characters in type literals:
|
|
170 // .0 - ' '
|
|
171 // .1 - '*'
|
|
172 // .2 - ';'
|
|
173 // .3 - ','
|
|
174 // .4 - '{'
|
|
175 // .5 - '}'
|
|
176 // .6 - '['
|
|
177 // .7 - ']'
|
|
178 // .8 - '('
|
|
179 // .9 - ')'
|
|
180 // This is unambiguous as, although the type literal can contain a dot
|
|
181 // as shown above, those dots are always followed by a name and names
|
|
182 // can not begin with a digit. A dot is always followed by a name or
|
|
183 // a digit, and a type literal can neither start nor end with a dot,
|
|
184 // so this never introduces consecutive dots.
|
|
185 //
|
|
186 // Struct tags can contain any character, so they need special
|
|
187 // treatment. Alphanumerics, underscores, and Unicode characters that
|
|
188 // require more than a single byte are left alone (Unicode characters
|
|
189 // will be encoded later, as described below). Other single bytes
|
|
190 // characters are replace with .xNN where NN is the hex encoding.
|
|
191 //
|
|
192 // Since Go identifiers can contain Unicode characters, we must encode
|
|
193 // them into ASCII. We do this last, after the name is generated as
|
|
194 // described above and after type literals are encoded. To make the
|
|
195 // encoding unambiguous, we introduce it with two consecutive dots.
|
|
196 // This is followed by the letter u and four hex digits or the letter
|
|
197 // U and eight digits, just as in the language only using ..u and ..U
|
145
|
198 // instead of \u and \U. The compiler also produces identifiers that
|
|
199 // are qualified by package path, which means that there may also be ASCII
|
|
200 // characters that are not assembler-friendly (ex: '=', '/'). The encoding
|
|
201 // scheme translates such characters into the "..zNN" where NN is the
|
|
202 // hex value for the character. Since before this encoding names can never
|
|
203 // contain consecutive dots followed by 'z', 'u' or 'U', and after this
|
|
204 // encoding "..z", "..u" and "..U" are followed by a known number of
|
131
|
205 // characters, this is unambiguous.
|
|
206 //
|
|
207 // Demangling these names is straightforward:
|
145
|
208 // - replace ..zXX with an ASCII character
|
131
|
209 // - replace ..uXXXX with a unicode character
|
|
210 // - replace ..UXXXXXXXX with a unicode character
|
|
211 // - replace .D, where D is a digit, with the character from the above
|
|
212 // That will get you as close as possible to a readable name.
|
|
213
|
111
|
214 // Return the assembler name to use for an exported function, a
|
|
215 // method, or a function/method declaration. This is not called if
|
|
216 // the function has been given an explicit name via a magic //extern
|
|
217 // or //go:linkname comment. GO_NAME is the name that appears in the
|
|
218 // Go code. PACKAGE is the package where the function is defined, and
|
|
219 // is NULL for the package being compiled. For a method, RTYPE is
|
|
220 // the method's receiver type; for a function, RTYPE is NULL.
|
|
221
|
|
222 std::string
|
|
223 Gogo::function_asm_name(const std::string& go_name, const Package* package,
|
|
224 const Type* rtype)
|
|
225 {
|
131
|
226 std::string ret;
|
111
|
227 if (rtype != NULL)
|
131
|
228 ret = rtype->deref()->mangled_name(this);
|
|
229 else if (package == NULL)
|
145
|
230 ret = this->pkgpath();
|
131
|
231 else
|
145
|
232 ret = package->pkgpath();
|
131
|
233 ret.push_back('.');
|
|
234 // Check for special names that will break if we use
|
|
235 // Gogo::unpack_hidden_name.
|
|
236 if (Gogo::is_special_name(go_name))
|
|
237 ret.append(go_name);
|
|
238 else
|
|
239 ret.append(Gogo::unpack_hidden_name(go_name));
|
111
|
240 return go_encode_id(ret);
|
|
241 }
|
|
242
|
|
243 // Return the name to use for a function descriptor. These symbols
|
|
244 // are globally visible.
|
|
245
|
|
246 std::string
|
|
247 Gogo::function_descriptor_name(Named_object* no)
|
|
248 {
|
131
|
249 if (no->is_function() && !no->func_value()->asm_name().empty())
|
|
250 return no->func_value()->asm_name() + "..f";
|
|
251 else if (no->is_function_declaration()
|
|
252 && !no->func_declaration_value()->asm_name().empty())
|
|
253 return no->func_declaration_value()->asm_name() + "..f";
|
|
254 std::string ret = this->function_asm_name(no->name(), no->package(), NULL);
|
|
255 ret.append("..f");
|
|
256 return ret;
|
111
|
257 }
|
|
258
|
|
259 // Return the name to use for a generated stub method. MNAME is the
|
131
|
260 // method name. PACKAGE is the package where the type that needs this
|
|
261 // stub method is defined. These functions are globally visible.
|
|
262 // Note that this is the function name that corresponds to the name
|
|
263 // used for the method in Go source code, if this stub method were
|
|
264 // written in Go. The assembler name will be generated by
|
|
265 // Gogo::function_asm_name, and because this is a method that name
|
|
266 // will include the receiver type.
|
111
|
267
|
|
268 std::string
|
131
|
269 Gogo::stub_method_name(const Package* package, const std::string& mname)
|
111
|
270 {
|
131
|
271 if (!Gogo::is_hidden_name(mname))
|
|
272 return mname + "..stub";
|
|
273
|
|
274 const std::string& ppkgpath(package == NULL
|
|
275 ? this->pkgpath()
|
|
276 : package->pkgpath());
|
|
277 std::string mpkgpath = Gogo::hidden_name_pkgpath(mname);
|
|
278 if (mpkgpath == ppkgpath)
|
|
279 return Gogo::unpack_hidden_name(mname) + "..stub";
|
|
280
|
|
281 // We are creating a stub method for an unexported method of an
|
|
282 // imported embedded type. We need to disambiguate the method name.
|
145
|
283 std::string ret = mpkgpath;
|
131
|
284 ret.push_back('.');
|
|
285 ret.append(Gogo::unpack_hidden_name(mname));
|
|
286 ret.append("..stub");
|
|
287 return ret;
|
111
|
288 }
|
|
289
|
145
|
290 // Return the name of the hash function for TYPE.
|
111
|
291
|
145
|
292 std::string
|
|
293 Gogo::hash_function_name(const Type* type)
|
|
294 {
|
|
295 std::string tname = type->mangled_name(this);
|
|
296 return tname + "..hash";
|
|
297 }
|
|
298
|
|
299 // Return the name of the equal function for TYPE. If NAME is not
|
|
300 // NULL it is the name of the type.
|
|
301
|
|
302 std::string
|
|
303 Gogo::equal_function_name(const Type* type, const Named_type* name)
|
111
|
304 {
|
131
|
305 const Type* rtype = type;
|
|
306 if (name != NULL)
|
|
307 rtype = name;
|
|
308 std::string tname = rtype->mangled_name(this);
|
145
|
309 return tname + "..eq";
|
111
|
310 }
|
|
311
|
|
312 // Return the assembler name to use for a global variable. GO_NAME is
|
|
313 // the name that appears in the Go code. PACKAGE is the package where
|
|
314 // the variable is defined, and is NULL for the package being
|
|
315 // compiled.
|
|
316
|
|
317 std::string
|
|
318 Gogo::global_var_asm_name(const std::string& go_name, const Package* package)
|
|
319 {
|
131
|
320 std::string ret;
|
|
321 if (package == NULL)
|
145
|
322 ret = this->pkgpath();
|
131
|
323 else
|
145
|
324 ret = package->pkgpath();
|
131
|
325 ret.append(1, '.');
|
111
|
326 ret.append(Gogo::unpack_hidden_name(go_name));
|
|
327 return go_encode_id(ret);
|
|
328 }
|
|
329
|
|
330 // Return an erroneous name that indicates that an error has already
|
|
331 // been reported.
|
|
332
|
|
333 std::string
|
|
334 Gogo::erroneous_name()
|
|
335 {
|
131
|
336 go_assert(saw_errors());
|
111
|
337 static int erroneous_count;
|
|
338 char name[50];
|
131
|
339 snprintf(name, sizeof name, ".erroneous%d", erroneous_count);
|
111
|
340 ++erroneous_count;
|
|
341 return name;
|
|
342 }
|
|
343
|
|
344 // Return whether a name is an erroneous name.
|
|
345
|
|
346 bool
|
|
347 Gogo::is_erroneous_name(const std::string& name)
|
|
348 {
|
131
|
349 return name.compare(0, 10, ".erroneous") == 0;
|
111
|
350 }
|
|
351
|
|
352 // Return a name for a thunk object.
|
|
353
|
|
354 std::string
|
|
355 Gogo::thunk_name()
|
|
356 {
|
|
357 static int thunk_count;
|
|
358 char thunk_name[50];
|
131
|
359 snprintf(thunk_name, sizeof thunk_name, "..thunk%d", thunk_count);
|
111
|
360 ++thunk_count;
|
145
|
361 std::string ret = this->pkgpath();
|
131
|
362 return ret + thunk_name;
|
111
|
363 }
|
|
364
|
|
365 // Return whether a function is a thunk.
|
|
366
|
|
367 bool
|
|
368 Gogo::is_thunk(const Named_object* no)
|
|
369 {
|
131
|
370 const std::string& name(no->name());
|
|
371 size_t i = name.find("..thunk");
|
|
372 if (i == std::string::npos)
|
|
373 return false;
|
|
374 for (i += 7; i < name.size(); ++i)
|
|
375 if (name[i] < '0' || name[i] > '9')
|
|
376 return false;
|
|
377 return true;
|
111
|
378 }
|
|
379
|
|
380 // Return the name to use for an init function. There can be multiple
|
|
381 // functions named "init" so each one needs a different name.
|
|
382
|
|
383 std::string
|
|
384 Gogo::init_function_name()
|
|
385 {
|
|
386 static int init_count;
|
|
387 char buf[30];
|
131
|
388 snprintf(buf, sizeof buf, "..init%d", init_count);
|
111
|
389 ++init_count;
|
145
|
390 std::string ret = this->pkgpath();
|
131
|
391 return ret + buf;
|
111
|
392 }
|
|
393
|
|
394 // Return the name to use for a nested function.
|
|
395
|
|
396 std::string
|
131
|
397 Gogo::nested_function_name(Named_object* enclosing)
|
111
|
398 {
|
131
|
399 std::string prefix;
|
|
400 unsigned int index;
|
|
401 if (enclosing == NULL)
|
|
402 {
|
|
403 // A function literal at top level, as in
|
|
404 // var f = func() {}
|
|
405 static unsigned int toplevel_index;
|
|
406 ++toplevel_index;
|
|
407 index = toplevel_index;
|
|
408 prefix = ".go";
|
|
409 }
|
|
410 else
|
|
411 {
|
|
412 while (true)
|
|
413 {
|
|
414 Named_object* parent = enclosing->func_value()->enclosing();
|
|
415 if (parent == NULL)
|
|
416 break;
|
|
417 enclosing = parent;
|
|
418 }
|
|
419 const Typed_identifier* rcvr =
|
|
420 enclosing->func_value()->type()->receiver();
|
|
421 if (rcvr != NULL)
|
|
422 {
|
|
423 prefix = rcvr->type()->mangled_name(this);
|
|
424 prefix.push_back('.');
|
|
425 }
|
|
426 prefix.append(Gogo::unpack_hidden_name(enclosing->name()));
|
|
427 index = enclosing->func_value()->next_nested_function_index();
|
|
428 }
|
111
|
429 char buf[30];
|
131
|
430 snprintf(buf, sizeof buf, "..func%u", index);
|
|
431 return prefix + buf;
|
111
|
432 }
|
|
433
|
|
434 // Return the name to use for a sink function, a function whose name
|
|
435 // is simply underscore. We don't really need these functions but we
|
|
436 // do have to generate them for error checking.
|
|
437
|
|
438 std::string
|
|
439 Gogo::sink_function_name()
|
|
440 {
|
|
441 static int sink_count;
|
|
442 char buf[30];
|
131
|
443 snprintf(buf, sizeof buf, ".sink%d", sink_count);
|
111
|
444 ++sink_count;
|
|
445 return buf;
|
|
446 }
|
|
447
|
|
448 // Return the name to use for a redefined function. These functions
|
|
449 // are erroneous but we still generate them for further error
|
|
450 // checking.
|
|
451
|
|
452 std::string
|
|
453 Gogo::redefined_function_name()
|
|
454 {
|
|
455 static int redefinition_count;
|
|
456 char buf[30];
|
131
|
457 snprintf(buf, sizeof buf, ".redefined%d", redefinition_count);
|
111
|
458 ++redefinition_count;
|
|
459 return buf;
|
|
460 }
|
|
461
|
|
462 // Return the name to use for a recover thunk for the function NAME.
|
|
463 // If the function is a method, RTYPE is the receiver type.
|
|
464
|
|
465 std::string
|
|
466 Gogo::recover_thunk_name(const std::string& name, const Type* rtype)
|
|
467 {
|
131
|
468 std::string ret;
|
111
|
469 if (rtype != NULL)
|
|
470 {
|
131
|
471 ret = rtype->mangled_name(this);
|
|
472 ret.append(1, '.');
|
111
|
473 }
|
131
|
474 if (Gogo::is_special_name(name))
|
|
475 ret.append(name);
|
|
476 else
|
|
477 ret.append(Gogo::unpack_hidden_name(name));
|
|
478 ret.append("..r");
|
111
|
479 return ret;
|
|
480 }
|
|
481
|
|
482 // Return the name to use for a GC root variable. The GC root
|
|
483 // variable is a composite literal that is passed to
|
|
484 // runtime.registerGCRoots. There is at most one of these variables
|
|
485 // per compilation.
|
|
486
|
|
487 std::string
|
|
488 Gogo::gc_root_name()
|
|
489 {
|
131
|
490 return "go..C0";
|
111
|
491 }
|
|
492
|
|
493 // Return the name to use for a composite literal or string
|
|
494 // initializer. This is a local name never referenced outside of this
|
|
495 // file.
|
|
496
|
|
497 std::string
|
|
498 Gogo::initializer_name()
|
|
499 {
|
|
500 static unsigned int counter;
|
|
501 char buf[30];
|
|
502 ++counter;
|
131
|
503 snprintf(buf, sizeof buf, "go..C%u", counter);
|
111
|
504 return buf;
|
|
505 }
|
|
506
|
|
507 // Return the name of the variable used to represent the zero value of
|
|
508 // a map. This is a globally visible common symbol.
|
|
509
|
|
510 std::string
|
|
511 Gogo::map_zero_value_name()
|
|
512 {
|
131
|
513 return "go..zerovalue";
|
111
|
514 }
|
|
515
|
|
516 // Return the name to use for the import control function.
|
|
517
|
|
518 const std::string&
|
|
519 Gogo::get_init_fn_name()
|
|
520 {
|
|
521 if (this->init_fn_name_.empty())
|
|
522 {
|
|
523 go_assert(this->package_ != NULL);
|
|
524 if (this->is_main_package())
|
|
525 {
|
|
526 // Use a name that the runtime knows.
|
|
527 this->init_fn_name_ = "__go_init_main";
|
|
528 }
|
|
529 else
|
|
530 {
|
|
531 std::string s = this->pkgpath_symbol();
|
|
532 s.append("..import");
|
|
533 this->init_fn_name_ = s;
|
|
534 }
|
|
535 }
|
|
536
|
|
537 return this->init_fn_name_;
|
|
538 }
|
|
539
|
145
|
540 // Return the name for a dummy init function, which is not a real
|
|
541 // function but only for tracking transitive import.
|
|
542
|
|
543 std::string
|
|
544 Gogo::dummy_init_fn_name()
|
|
545 {
|
|
546 return "~" + this->pkgpath_symbol();
|
|
547 }
|
|
548
|
|
549 // Return the package path symbol from an init function name, which
|
|
550 // can be a real init function or a dummy one.
|
|
551
|
|
552 std::string
|
|
553 Gogo::pkgpath_from_init_fn_name(std::string name)
|
|
554 {
|
|
555 go_assert(!name.empty());
|
|
556 if (name[0] == '~')
|
|
557 return name.substr(1);
|
|
558 size_t pos = name.find("..import");
|
|
559 if (pos != std::string::npos)
|
|
560 return name.substr(0, pos);
|
|
561 go_unreachable();
|
|
562 }
|
|
563
|
111
|
564 // Return a mangled name for a type. These names appear in symbol
|
|
565 // names in the assembler file for things like type descriptors and
|
|
566 // methods.
|
|
567
|
|
568 std::string
|
|
569 Type::mangled_name(Gogo* gogo) const
|
|
570 {
|
|
571 std::string ret;
|
|
572
|
131
|
573 // The do_mangled_name virtual function will set RET to the mangled
|
|
574 // name before glue character mapping.
|
111
|
575 this->do_mangled_name(gogo, &ret);
|
|
576
|
131
|
577 // Type descriptor names and interface method table names use a ".."
|
|
578 // before the mangled name of a type, so to avoid ambiguity the
|
|
579 // mangled name must not start with 'u' or 'U' or a digit.
|
|
580 go_assert((ret[0] < '0' || ret[0] > '9') && ret[0] != ' ');
|
|
581 if (ret[0] == 'u' || ret[0] == 'U')
|
|
582 ret = " " + ret;
|
|
583
|
|
584 // Map glue characters as described above.
|
|
585
|
|
586 // The mapping is only unambiguous if there is no .DIGIT in the
|
|
587 // string, so check that.
|
|
588 for (size_t i = ret.find('.');
|
|
589 i != std::string::npos;
|
|
590 i = ret.find('.', i + 1))
|
|
591 {
|
|
592 if (i + 1 < ret.size())
|
|
593 {
|
|
594 char c = ret[i + 1];
|
|
595 go_assert(c < '0' || c > '9');
|
|
596 }
|
|
597 }
|
|
598
|
|
599 // The order of these characters is the replacement code.
|
|
600 const char * const replace = " *;,{}[]()";
|
|
601
|
|
602 const size_t rlen = strlen(replace);
|
|
603 char buf[2];
|
|
604 buf[0] = '.';
|
|
605 for (size_t ri = 0; ri < rlen; ++ri)
|
|
606 {
|
|
607 buf[1] = '0' + ri;
|
|
608 while (true)
|
|
609 {
|
|
610 size_t i = ret.find(replace[ri]);
|
|
611 if (i == std::string::npos)
|
|
612 break;
|
|
613 ret.replace(i, 1, buf, 2);
|
|
614 }
|
|
615 }
|
|
616
|
111
|
617 return ret;
|
|
618 }
|
|
619
|
|
620 // The mangled name is implemented as a method on each instance of
|
|
621 // Type.
|
|
622
|
|
623 void
|
|
624 Error_type::do_mangled_name(Gogo*, std::string* ret) const
|
|
625 {
|
131
|
626 ret->append("{error}");
|
111
|
627 }
|
|
628
|
|
629 void
|
|
630 Void_type::do_mangled_name(Gogo*, std::string* ret) const
|
|
631 {
|
131
|
632 ret->append("{void}");
|
111
|
633 }
|
|
634
|
|
635 void
|
|
636 Boolean_type::do_mangled_name(Gogo*, std::string* ret) const
|
|
637 {
|
131
|
638 ret->append("bool");
|
111
|
639 }
|
|
640
|
|
641 void
|
|
642 Integer_type::do_mangled_name(Gogo*, std::string* ret) const
|
|
643 {
|
|
644 char buf[100];
|
131
|
645 snprintf(buf, sizeof buf, "%s%si%d",
|
|
646 this->is_abstract_ ? "{abstract}" : "",
|
111
|
647 this->is_unsigned_ ? "u" : "",
|
|
648 this->bits_);
|
|
649 ret->append(buf);
|
|
650 }
|
|
651
|
|
652 void
|
|
653 Float_type::do_mangled_name(Gogo*, std::string* ret) const
|
|
654 {
|
|
655 char buf[100];
|
131
|
656 snprintf(buf, sizeof buf, "%sfloat%d",
|
|
657 this->is_abstract_ ? "{abstract}" : "",
|
111
|
658 this->bits_);
|
|
659 ret->append(buf);
|
|
660 }
|
|
661
|
|
662 void
|
|
663 Complex_type::do_mangled_name(Gogo*, std::string* ret) const
|
|
664 {
|
|
665 char buf[100];
|
131
|
666 snprintf(buf, sizeof buf, "%sc%d",
|
|
667 this->is_abstract_ ? "{abstract}" : "",
|
111
|
668 this->bits_);
|
|
669 ret->append(buf);
|
|
670 }
|
|
671
|
|
672 void
|
|
673 String_type::do_mangled_name(Gogo*, std::string* ret) const
|
|
674 {
|
131
|
675 ret->append("string");
|
111
|
676 }
|
|
677
|
|
678 void
|
|
679 Function_type::do_mangled_name(Gogo* gogo, std::string* ret) const
|
|
680 {
|
131
|
681 ret->append("func");
|
111
|
682
|
|
683 if (this->receiver_ != NULL)
|
|
684 {
|
131
|
685 ret->push_back('(');
|
111
|
686 this->append_mangled_name(this->receiver_->type(), gogo, ret);
|
131
|
687 ret->append(")");
|
111
|
688 }
|
|
689
|
131
|
690 ret->push_back('(');
|
111
|
691 const Typed_identifier_list* params = this->parameters();
|
|
692 if (params != NULL)
|
|
693 {
|
131
|
694 bool first = true;
|
111
|
695 for (Typed_identifier_list::const_iterator p = params->begin();
|
|
696 p != params->end();
|
|
697 ++p)
|
131
|
698 {
|
|
699 if (first)
|
|
700 first = false;
|
|
701 else
|
|
702 ret->push_back(',');
|
|
703 if (this->is_varargs_ && p + 1 == params->end())
|
|
704 {
|
|
705 // We can't use "..." here because the mangled name
|
|
706 // might start with 'u' or 'U', which would be ambiguous
|
|
707 // with the encoding of Unicode characters.
|
|
708 ret->append(",,,");
|
|
709 }
|
|
710 this->append_mangled_name(p->type(), gogo, ret);
|
|
711 }
|
111
|
712 }
|
131
|
713 ret->push_back(')');
|
111
|
714
|
131
|
715 ret->push_back('(');
|
111
|
716 const Typed_identifier_list* results = this->results();
|
|
717 if (results != NULL)
|
|
718 {
|
131
|
719 bool first = true;
|
111
|
720 for (Typed_identifier_list::const_iterator p = results->begin();
|
|
721 p != results->end();
|
|
722 ++p)
|
131
|
723 {
|
|
724 if (first)
|
|
725 first = false;
|
|
726 else
|
|
727 ret->append(",");
|
|
728 this->append_mangled_name(p->type(), gogo, ret);
|
|
729 }
|
111
|
730 }
|
131
|
731 ret->push_back(')');
|
111
|
732 }
|
|
733
|
|
734 void
|
|
735 Pointer_type::do_mangled_name(Gogo* gogo, std::string* ret) const
|
|
736 {
|
131
|
737 ret->push_back('*');
|
111
|
738 this->append_mangled_name(this->to_type_, gogo, ret);
|
|
739 }
|
|
740
|
|
741 void
|
|
742 Nil_type::do_mangled_name(Gogo*, std::string* ret) const
|
|
743 {
|
131
|
744 ret->append("{nil}");
|
111
|
745 }
|
|
746
|
|
747 void
|
|
748 Struct_type::do_mangled_name(Gogo* gogo, std::string* ret) const
|
|
749 {
|
131
|
750 ret->append("struct{");
|
|
751
|
|
752 if (this->is_struct_incomparable_)
|
|
753 ret->append("{x}");
|
111
|
754
|
|
755 const Struct_field_list* fields = this->fields_;
|
|
756 if (fields != NULL)
|
|
757 {
|
131
|
758 bool first = true;
|
111
|
759 for (Struct_field_list::const_iterator p = fields->begin();
|
|
760 p != fields->end();
|
|
761 ++p)
|
|
762 {
|
131
|
763 if (first)
|
|
764 first = false;
|
111
|
765 else
|
131
|
766 ret->push_back(';');
|
111
|
767
|
131
|
768 if (!p->is_anonymous())
|
|
769 {
|
145
|
770 Gogo::append_possibly_hidden_name(ret, p->field_name());
|
131
|
771 ret->push_back(' ');
|
111
|
772 }
|
|
773
|
|
774 // For an anonymous field with an alias type, the field name
|
|
775 // is the alias name.
|
|
776 if (p->is_anonymous()
|
|
777 && p->type()->named_type() != NULL
|
|
778 && p->type()->named_type()->is_alias())
|
|
779 p->type()->named_type()->append_mangled_type_name(gogo, true, ret);
|
|
780 else
|
|
781 this->append_mangled_name(p->type(), gogo, ret);
|
131
|
782
|
111
|
783 if (p->has_tag())
|
|
784 {
|
131
|
785 // Use curly braces around a struct tag, since they are
|
|
786 // unambiguous here and we have no encoding for
|
|
787 // quotation marks.
|
|
788 ret->push_back('{');
|
|
789 ret->append(go_mangle_struct_tag(p->tag()));
|
|
790 ret->push_back('}');
|
111
|
791 }
|
|
792 }
|
|
793 }
|
|
794
|
131
|
795 ret->push_back('}');
|
111
|
796 }
|
|
797
|
|
798 void
|
|
799 Array_type::do_mangled_name(Gogo* gogo, std::string* ret) const
|
|
800 {
|
131
|
801 ret->push_back('[');
|
111
|
802 if (this->length_ != NULL)
|
|
803 {
|
|
804 Numeric_constant nc;
|
|
805 if (!this->length_->numeric_constant_value(&nc))
|
|
806 {
|
|
807 go_assert(saw_errors());
|
|
808 return;
|
|
809 }
|
|
810 mpz_t val;
|
|
811 if (!nc.to_int(&val))
|
|
812 {
|
|
813 go_assert(saw_errors());
|
|
814 return;
|
|
815 }
|
|
816 char *s = mpz_get_str(NULL, 10, val);
|
|
817 ret->append(s);
|
|
818 free(s);
|
|
819 mpz_clear(val);
|
|
820 if (this->is_array_incomparable_)
|
131
|
821 ret->append("x");
|
111
|
822 }
|
131
|
823 ret->push_back(']');
|
|
824 this->append_mangled_name(this->element_type_, gogo, ret);
|
111
|
825 }
|
|
826
|
|
827 void
|
|
828 Map_type::do_mangled_name(Gogo* gogo, std::string* ret) const
|
|
829 {
|
131
|
830 ret->append("map[");
|
111
|
831 this->append_mangled_name(this->key_type_, gogo, ret);
|
131
|
832 ret->push_back(']');
|
111
|
833 this->append_mangled_name(this->val_type_, gogo, ret);
|
|
834 }
|
|
835
|
|
836 void
|
|
837 Channel_type::do_mangled_name(Gogo* gogo, std::string* ret) const
|
|
838 {
|
131
|
839 if (!this->may_send_)
|
|
840 ret->append("{}");
|
|
841 ret->append("chan");
|
|
842 if (!this->may_receive_)
|
|
843 ret->append("{}");
|
|
844 ret->push_back(' ');
|
111
|
845 this->append_mangled_name(this->element_type_, gogo, ret);
|
|
846 }
|
|
847
|
|
848 void
|
|
849 Interface_type::do_mangled_name(Gogo* gogo, std::string* ret) const
|
|
850 {
|
|
851 go_assert(this->methods_are_finalized_);
|
|
852
|
131
|
853 ret->append("interface{");
|
111
|
854
|
|
855 const Typed_identifier_list* methods = this->all_methods_;
|
|
856 if (methods != NULL && !this->seen_)
|
|
857 {
|
|
858 this->seen_ = true;
|
131
|
859 bool first = true;
|
111
|
860 for (Typed_identifier_list::const_iterator p = methods->begin();
|
|
861 p != methods->end();
|
|
862 ++p)
|
|
863 {
|
131
|
864 if (first)
|
|
865 first = false;
|
|
866 else
|
|
867 ret->push_back(';');
|
|
868
|
111
|
869 if (!p->name().empty())
|
|
870 {
|
145
|
871 Gogo::append_possibly_hidden_name(ret, p->name());
|
131
|
872 ret->push_back(' ');
|
111
|
873 }
|
131
|
874
|
111
|
875 this->append_mangled_name(p->type(), gogo, ret);
|
|
876 }
|
|
877 this->seen_ = false;
|
|
878 }
|
|
879
|
131
|
880 ret->push_back('}');
|
111
|
881 }
|
|
882
|
|
883 void
|
|
884 Named_type::do_mangled_name(Gogo* gogo, std::string* ret) const
|
|
885 {
|
|
886 this->append_mangled_type_name(gogo, false, ret);
|
|
887 }
|
|
888
|
|
889 void
|
|
890 Forward_declaration_type::do_mangled_name(Gogo* gogo, std::string* ret) const
|
|
891 {
|
|
892 if (this->is_defined())
|
|
893 this->append_mangled_name(this->real_type(), gogo, ret);
|
|
894 else
|
|
895 {
|
|
896 const Named_object* no = this->named_object();
|
|
897 if (no->package() == NULL)
|
145
|
898 ret->append(gogo->pkgpath());
|
111
|
899 else
|
145
|
900 ret->append(no->package()->pkgpath());
|
131
|
901 ret->push_back('.');
|
|
902 ret->append(Gogo::unpack_hidden_name(no->name()));
|
111
|
903 }
|
|
904 }
|
|
905
|
|
906 // Append the mangled name for a named type to RET. For an alias we
|
|
907 // normally use the real name, but if USE_ALIAS is true we use the
|
|
908 // alias name itself.
|
|
909
|
|
910 void
|
|
911 Named_type::append_mangled_type_name(Gogo* gogo, bool use_alias,
|
|
912 std::string* ret) const
|
|
913 {
|
|
914 if (this->is_error_)
|
|
915 return;
|
|
916 if (this->is_alias_ && !use_alias)
|
|
917 {
|
|
918 if (this->seen_alias_)
|
|
919 return;
|
|
920 this->seen_alias_ = true;
|
|
921 this->append_mangled_name(this->type_, gogo, ret);
|
|
922 this->seen_alias_ = false;
|
|
923 return;
|
|
924 }
|
|
925 Named_object* no = this->named_object_;
|
|
926 std::string name;
|
|
927 if (this->is_builtin())
|
|
928 go_assert(this->in_function_ == NULL);
|
|
929 else
|
|
930 {
|
|
931 if (this->in_function_ != NULL)
|
|
932 {
|
|
933 const Typed_identifier* rcvr =
|
|
934 this->in_function_->func_value()->type()->receiver();
|
|
935 if (rcvr != NULL)
|
131
|
936 ret->append(rcvr->type()->deref()->mangled_name(gogo));
|
|
937 else if (this->in_function_->package() == NULL)
|
145
|
938 ret->append(gogo->pkgpath());
|
131
|
939 else
|
145
|
940 ret->append(this->in_function_->package()->pkgpath());
|
131
|
941 ret->push_back('.');
|
|
942 ret->append(Gogo::unpack_hidden_name(this->in_function_->name()));
|
111
|
943 }
|
131
|
944 else
|
|
945 {
|
|
946 if (no->package() == NULL)
|
145
|
947 ret->append(gogo->pkgpath());
|
131
|
948 else
|
145
|
949 ret->append(no->package()->pkgpath());
|
131
|
950 }
|
|
951 ret->push_back('.');
|
111
|
952 }
|
131
|
953
|
|
954 ret->append(Gogo::unpack_hidden_name(no->name()));
|
|
955
|
|
956 if (this->in_function_ != NULL && this->in_function_index_ > 0)
|
|
957 {
|
|
958 char buf[30];
|
|
959 snprintf(buf, sizeof buf, "..i%u", this->in_function_index_);
|
|
960 ret->append(buf);
|
|
961 }
|
111
|
962 }
|
|
963
|
|
964 // Return the name for the type descriptor symbol for TYPE. This can
|
|
965 // be a global, common, or local symbol, depending. NT is not NULL if
|
|
966 // it is the name to use.
|
|
967
|
|
968 std::string
|
145
|
969 Gogo::type_descriptor_name(const Type* type, Named_type* nt)
|
111
|
970 {
|
|
971 // The type descriptor symbol for the unsafe.Pointer type is defined
|
|
972 // in libgo/runtime/go-unsafe-pointer.c, so just use a reference to
|
131
|
973 // that symbol for all unsafe pointer types.
|
111
|
974 if (type->is_unsafe_pointer_type())
|
131
|
975 return "unsafe.Pointer..d";
|
111
|
976
|
|
977 if (nt == NULL)
|
131
|
978 return "type.." + type->mangled_name(this);
|
111
|
979
|
131
|
980 std::string ret;
|
111
|
981 Named_object* no = nt->named_object();
|
|
982 unsigned int index;
|
|
983 const Named_object* in_function = nt->in_function(&index);
|
|
984 if (nt->is_builtin())
|
|
985 go_assert(in_function == NULL);
|
|
986 else
|
|
987 {
|
|
988 if (in_function != NULL)
|
|
989 {
|
|
990 const Typed_identifier* rcvr =
|
|
991 in_function->func_value()->type()->receiver();
|
|
992 if (rcvr != NULL)
|
131
|
993 ret.append(rcvr->type()->deref()->mangled_name(this));
|
|
994 else if (in_function->package() == NULL)
|
145
|
995 ret.append(this->pkgpath());
|
131
|
996 else
|
145
|
997 ret.append(in_function->package()->pkgpath());
|
131
|
998 ret.push_back('.');
|
111
|
999 ret.append(Gogo::unpack_hidden_name(in_function->name()));
|
131
|
1000 ret.push_back('.');
|
111
|
1001 }
|
131
|
1002
|
|
1003 if (no->package() == NULL)
|
145
|
1004 ret.append(this->pkgpath());
|
131
|
1005 else
|
145
|
1006 ret.append(no->package()->pkgpath());
|
131
|
1007 ret.push_back('.');
|
111
|
1008 }
|
|
1009
|
145
|
1010 Gogo::append_possibly_hidden_name(&ret, no->name());
|
131
|
1011
|
|
1012 if (in_function != NULL && index > 0)
|
|
1013 {
|
|
1014 char buf[30];
|
|
1015 snprintf(buf, sizeof buf, "..i%u", index);
|
|
1016 ret.append(buf);
|
|
1017 }
|
|
1018
|
|
1019 ret.append("..d");
|
111
|
1020
|
|
1021 return ret;
|
|
1022 }
|
|
1023
|
145
|
1024 // Return the name of the type descriptor list symbol of a package.
|
|
1025
|
|
1026 std::string
|
|
1027 Gogo::type_descriptor_list_symbol(std::string pkgpath)
|
|
1028 {
|
|
1029 return pkgpath + "..types";
|
|
1030 }
|
|
1031
|
|
1032 // Return the name of the list of all type descriptor lists. This is
|
|
1033 // only used in the main package.
|
|
1034
|
|
1035 std::string
|
|
1036 Gogo::typelists_symbol()
|
|
1037 {
|
|
1038 return "go..typelists";
|
|
1039 }
|
|
1040
|
111
|
1041 // Return the name for the GC symbol for a type. This is used to
|
|
1042 // initialize the gcdata field of a type descriptor. This is a local
|
|
1043 // name never referenced outside of this assembly file. (Note that
|
|
1044 // some type descriptors will initialize the gcdata field with a name
|
|
1045 // generated by ptrmask_symbol_name rather than this method.)
|
|
1046
|
|
1047 std::string
|
|
1048 Gogo::gc_symbol_name(Type* type)
|
|
1049 {
|
131
|
1050 return this->type_descriptor_name(type, type->named_type()) + "..g";
|
111
|
1051 }
|
|
1052
|
|
1053 // Return the name for a ptrmask variable. PTRMASK_SYM_NAME is a
|
131
|
1054 // base32 string encoding the ptrmask (as returned by Ptrmask::symname
|
111
|
1055 // in types.cc). This name is used to intialize the gcdata field of a
|
|
1056 // type descriptor. These names are globally visible. (Note that
|
|
1057 // some type descriptors will initialize the gcdata field with a name
|
|
1058 // generated by gc_symbol_name rather than this method.)
|
|
1059
|
|
1060 std::string
|
|
1061 Gogo::ptrmask_symbol_name(const std::string& ptrmask_sym_name)
|
|
1062 {
|
131
|
1063 return "gcbits.." + ptrmask_sym_name;
|
111
|
1064 }
|
|
1065
|
|
1066 // Return the name to use for an interface method table used for the
|
|
1067 // ordinary type TYPE converted to the interface type ITYPE.
|
|
1068 // IS_POINTER is true if this is for the method set for a pointer
|
|
1069 // receiver.
|
|
1070
|
|
1071 std::string
|
|
1072 Gogo::interface_method_table_name(Interface_type* itype, Type* type,
|
|
1073 bool is_pointer)
|
|
1074 {
|
131
|
1075 return ((is_pointer ? "pimt.." : "imt..")
|
111
|
1076 + itype->mangled_name(this)
|
131
|
1077 + ".."
|
111
|
1078 + type->mangled_name(this));
|
|
1079 }
|
131
|
1080
|
|
1081 // Return whether NAME is a special name that can not be passed to
|
|
1082 // unpack_hidden_name. This is needed because various special names
|
|
1083 // use "..SUFFIX", but unpack_hidden_name just looks for '.'.
|
|
1084
|
|
1085 bool
|
|
1086 Gogo::is_special_name(const std::string& name)
|
|
1087 {
|
|
1088 return (name.find("..hash") != std::string::npos
|
|
1089 || name.find("..eq") != std::string::npos
|
|
1090 || name.find("..stub") != std::string::npos
|
|
1091 || name.find("..func") != std::string::npos
|
|
1092 || name.find("..r") != std::string::npos
|
|
1093 || name.find("..init") != std::string::npos
|
|
1094 || name.find("..thunk") != std::string::npos
|
|
1095 || name.find("..import") != std::string::npos);
|
|
1096 }
|