source: src/SymTab/Mangler.cc@ 5ad24a2c

Last change on this file since 5ad24a2c was a137d5a, checked in by Andrew Beach <ajbeach@…>, 2 years ago

Took out some old code from the new section of the Mangler.

  • Property mode set to 100644
File size: 29.8 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// Mangler.cc --
8//
9// Author : Richard C. Bilson
10// Created On : Sun May 17 21:40:29 2015
11// Last Modified By : Andrew Beach
12// Last Modified On : Fri Oct 21 16:18:00 2022
13// Update Count : 75
14//
15#include "Mangler.h"
16
17#include <algorithm> // for copy, transform
18#include <cassert> // for assert, assertf
19#include <functional> // for const_mem_fun_t, mem_fun
20#include <iterator> // for ostream_iterator, back_insert_ite...
21#include <list> // for _List_iterator, list, _List_const...
22#include <string> // for string, char_traits, operator<<
23
24#include "AST/Pass.hpp"
25#include "CodeGen/OperatorTable.h" // for OperatorInfo, operatorLookup
26#include "Common/PassVisitor.h"
27#include "Common/ToString.hpp" // for toCString
28#include "Common/SemanticError.h" // for SemanticError
29#include "ResolvExpr/TypeEnvironment.h" // for TypeEnvironment
30#include "SynTree/LinkageSpec.h" // for Spec, isOverridable, AutoGen, Int...
31#include "SynTree/Declaration.h" // for TypeDecl, DeclarationWithType
32#include "SynTree/Expression.h" // for TypeExpr, Expression, operator<<
33#include "SynTree/Type.h" // for Type, ReferenceToType, Type::Fora...
34
35namespace SymTab {
36 namespace Mangler {
37 namespace {
38 /// Mangles names to a unique C identifier
39 struct Mangler_old : public WithShortCircuiting, public WithVisitorRef<Mangler_old>, public WithGuards {
40 Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams );
41 Mangler_old( const Mangler_old & ) = delete;
42
43 void previsit( const BaseSyntaxNode * ) { visit_children = false; }
44
45 void postvisit( const ObjectDecl * declaration );
46 void postvisit( const FunctionDecl * declaration );
47 void postvisit( const TypeDecl * declaration );
48
49 void postvisit( const VoidType * voidType );
50 void postvisit( const BasicType * basicType );
51 void postvisit( const PointerType * pointerType );
52 void postvisit( const ArrayType * arrayType );
53 void postvisit( const ReferenceType * refType );
54 void postvisit( const FunctionType * functionType );
55 void postvisit( const StructInstType * aggregateUseType );
56 void postvisit( const UnionInstType * aggregateUseType );
57 void postvisit( const EnumInstType * aggregateUseType );
58 void postvisit( const TypeInstType * aggregateUseType );
59 void postvisit( const TraitInstType * inst );
60 void postvisit( const TupleType * tupleType );
61 void postvisit( const VarArgsType * varArgsType );
62 void postvisit( const ZeroType * zeroType );
63 void postvisit( const OneType * oneType );
64 void postvisit( const QualifiedType * qualType );
65
66 std::string get_mangleName() { return mangleName; }
67 private:
68 std::string mangleName; ///< Mangled name being constructed
69 typedef std::map< std::string, std::pair< int, int > > VarMapType;
70 VarMapType varNums; ///< Map of type variables to indices
71 int nextVarNum; ///< Next type variable index
72 bool isTopLevel; ///< Is the Mangler at the top level
73 bool mangleOverridable; ///< Specially mangle overridable built-in methods
74 bool typeMode; ///< Produce a unique mangled name for a type
75 bool mangleGenericParams; ///< Include generic parameters in name mangling if true
76 bool inFunctionType = false; ///< Include type qualifiers if false.
77 bool inQualifiedType = false; ///< Add start/end delimiters around qualified type
78
79 public:
80 Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
81 int nextVarNum, const VarMapType& varNums );
82
83 private:
84 void mangleDecl( const DeclarationWithType * declaration );
85 void mangleRef( const ReferenceToType * refType, std::string prefix );
86
87 void printQualifiers( const Type *type );
88 }; // Mangler_old
89 } // namespace
90
91 std::string mangle( const BaseSyntaxNode * decl, bool mangleOverridable, bool typeMode, bool mangleGenericParams ) {
92 PassVisitor<Mangler_old> mangler( mangleOverridable, typeMode, mangleGenericParams );
93 maybeAccept( decl, mangler );
94 return mangler.pass.get_mangleName();
95 }
96
97 std::string mangleType( const Type * ty ) {
98 PassVisitor<Mangler_old> mangler( false, true, true );
99 maybeAccept( ty, mangler );
100 return mangler.pass.get_mangleName();
101 }
102
103 std::string mangleConcrete( const Type * ty ) {
104 PassVisitor<Mangler_old> mangler( false, false, false );
105 maybeAccept( ty, mangler );
106 return mangler.pass.get_mangleName();
107 }
108
109 namespace {
110 Mangler_old::Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams )
111 : nextVarNum( 0 ), isTopLevel( true ),
112 mangleOverridable( mangleOverridable ), typeMode( typeMode ),
113 mangleGenericParams( mangleGenericParams ) {}
114
115 Mangler_old::Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
116 int nextVarNum, const VarMapType& varNums )
117 : varNums( varNums ), nextVarNum( nextVarNum ), isTopLevel( false ),
118 mangleOverridable( mangleOverridable ), typeMode( typeMode ),
119 mangleGenericParams( mangleGenericParams ) {}
120
121 void Mangler_old::mangleDecl( const DeclarationWithType * declaration ) {
122 bool wasTopLevel = isTopLevel;
123 if ( isTopLevel ) {
124 varNums.clear();
125 nextVarNum = 0;
126 isTopLevel = false;
127 } // if
128 mangleName += Encoding::manglePrefix;
129 const CodeGen::OperatorInfo * opInfo = CodeGen::operatorLookup( declaration->get_name() );
130 if ( opInfo ) {
131 mangleName += std::to_string( opInfo->outputName.size() ) + opInfo->outputName;
132 } else {
133 mangleName += std::to_string( declaration->name.size() ) + declaration->name;
134 } // if
135 maybeAccept( declaration->get_type(), *visitor );
136 if ( mangleOverridable && LinkageSpec::isOverridable( declaration->get_linkage() ) ) {
137 // want to be able to override autogenerated and intrinsic routines,
138 // so they need a different name mangling
139 if ( declaration->get_linkage() == LinkageSpec::AutoGen ) {
140 mangleName += Encoding::autogen;
141 } else if ( declaration->get_linkage() == LinkageSpec::Intrinsic ) {
142 mangleName += Encoding::intrinsic;
143 } else {
144 // if we add another kind of overridable function, this has to change
145 assert( false && "unknown overrideable linkage" );
146 } // if
147 }
148 isTopLevel = wasTopLevel;
149 }
150
151 void Mangler_old::postvisit( const ObjectDecl * declaration ) {
152 mangleDecl( declaration );
153 }
154
155 void Mangler_old::postvisit( const FunctionDecl * declaration ) {
156 mangleDecl( declaration );
157 }
158
159 void Mangler_old::postvisit( const VoidType * voidType ) {
160 printQualifiers( voidType );
161 mangleName += Encoding::void_t;
162 }
163
164 void Mangler_old::postvisit( const BasicType * basicType ) {
165 printQualifiers( basicType );
166 assertf( basicType->kind < BasicType::NUMBER_OF_BASIC_TYPES, "Unhandled basic type: %d", basicType->kind );
167 mangleName += Encoding::basicTypes[ basicType->kind ];
168 }
169
170 void Mangler_old::postvisit( const PointerType * pointerType ) {
171 printQualifiers( pointerType );
172 // mangle void (*f)() and void f() to the same name to prevent overloading on functions and function pointers
173 if ( ! dynamic_cast<FunctionType *>( pointerType->base ) ) mangleName += Encoding::pointer;
174 maybeAccept( pointerType->base, *visitor );
175 }
176
177 void Mangler_old::postvisit( const ArrayType * arrayType ) {
178 // TODO: encode dimension
179 printQualifiers( arrayType );
180 mangleName += Encoding::array + "0";
181 maybeAccept( arrayType->base, *visitor );
182 }
183
184 void Mangler_old::postvisit( const ReferenceType * refType ) {
185 // don't print prefix (e.g. 'R') for reference types so that references and non-references do not overload.
186 // Further, do not print the qualifiers for a reference type (but do run printQualifers because of TypeDecls, etc.),
187 // by pretending every reference type is a function parameter.
188 GuardValue( inFunctionType );
189 inFunctionType = true;
190 printQualifiers( refType );
191 maybeAccept( refType->base, *visitor );
192 }
193
194 namespace {
195 inline std::list< Type* > getTypes( const std::list< DeclarationWithType* > decls ) {
196 std::list< Type* > ret;
197 std::transform( decls.begin(), decls.end(), std::back_inserter( ret ),
198 std::mem_fun( &DeclarationWithType::get_type ) );
199 return ret;
200 }
201 }
202
203 void Mangler_old::postvisit( const FunctionType * functionType ) {
204 printQualifiers( functionType );
205 mangleName += Encoding::function;
206 // turn on inFunctionType so that printQualifiers does not print most qualifiers for function parameters,
207 // since qualifiers on outermost parameter type do not differentiate function types, e.g.,
208 // void (*)(const int) and void (*)(int) are the same type, but void (*)(const int *) and void (*)(int *) are different
209 GuardValue( inFunctionType );
210 inFunctionType = true;
211 std::list< Type* > returnTypes = getTypes( functionType->returnVals );
212 if (returnTypes.empty()) mangleName += Encoding::void_t;
213 else acceptAll( returnTypes, *visitor );
214 mangleName += "_";
215 std::list< Type* > paramTypes = getTypes( functionType->parameters );
216 acceptAll( paramTypes, *visitor );
217 mangleName += "_";
218 }
219
220 void Mangler_old::mangleRef( const ReferenceToType * refType, std::string prefix ) {
221 printQualifiers( refType );
222
223 mangleName += prefix + std::to_string( refType->name.length() ) + refType->name;
224
225 if ( mangleGenericParams ) {
226 const std::list< Expression* > & params = refType->parameters;
227 if ( ! params.empty() ) {
228 mangleName += "_";
229 for ( const Expression * param : params ) {
230 const TypeExpr * paramType = dynamic_cast< const TypeExpr * >( param );
231 assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString(param));
232 maybeAccept( paramType->type, *visitor );
233 }
234 mangleName += "_";
235 }
236 }
237 }
238
239 void Mangler_old::postvisit( const StructInstType * aggregateUseType ) {
240 mangleRef( aggregateUseType, Encoding::struct_t );
241 }
242
243 void Mangler_old::postvisit( const UnionInstType * aggregateUseType ) {
244 mangleRef( aggregateUseType, Encoding::union_t );
245 }
246
247 void Mangler_old::postvisit( const EnumInstType * aggregateUseType ) {
248 mangleRef( aggregateUseType, Encoding::enum_t );
249 }
250
251 void Mangler_old::postvisit( const TypeInstType * typeInst ) {
252 VarMapType::iterator varNum = varNums.find( typeInst->get_name() );
253 if ( varNum == varNums.end() ) {
254 mangleRef( typeInst, Encoding::type );
255 } else {
256 printQualifiers( typeInst );
257 // Note: Can't use name here, since type variable names do not actually disambiguate a function, e.g.
258 // forall(dtype T) void f(T);
259 // forall(dtype S) void f(S);
260 // are equivalent and should mangle the same way. This is accomplished by numbering the type variables when they
261 // are first found and prefixing with the appropriate encoding for the type class.
262 assertf( varNum->second.second < TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", varNum->second.second );
263 mangleName += Encoding::typeVariables[varNum->second.second] + std::to_string( varNum->second.first );
264 } // if
265 }
266
267 void Mangler_old::postvisit( const TraitInstType * inst ) {
268 printQualifiers( inst );
269 mangleName += std::to_string( inst->name.size() ) + inst->name;
270 }
271
272 void Mangler_old::postvisit( const TupleType * tupleType ) {
273 printQualifiers( tupleType );
274 mangleName += Encoding::tuple + std::to_string( tupleType->types.size() );
275 acceptAll( tupleType->types, *visitor );
276 }
277
278 void Mangler_old::postvisit( const VarArgsType * varArgsType ) {
279 printQualifiers( varArgsType );
280 static const std::string vargs = "__builtin_va_list";
281 mangleName += Encoding::type + std::to_string( vargs.size() ) + vargs;
282 }
283
284 void Mangler_old::postvisit( const ZeroType * ) {
285 mangleName += Encoding::zero;
286 }
287
288 void Mangler_old::postvisit( const OneType * ) {
289 mangleName += Encoding::one;
290 }
291
292 void Mangler_old::postvisit( const QualifiedType * qualType ) {
293 bool inqual = inQualifiedType;
294 if (! inqual ) {
295 // N marks the start of a qualified type
296 inQualifiedType = true;
297 mangleName += Encoding::qualifiedTypeStart;
298 }
299 maybeAccept( qualType->parent, *visitor );
300 maybeAccept( qualType->child, *visitor );
301 if ( ! inqual ) {
302 // E marks the end of a qualified type
303 inQualifiedType = false;
304 mangleName += Encoding::qualifiedTypeEnd;
305 }
306 }
307
308 void Mangler_old::postvisit( const TypeDecl * decl ) {
309 // TODO: is there any case where mangling a TypeDecl makes sense? If so, this code needs to be
310 // fixed to ensure that two TypeDecls mangle to the same name when they are the same type and vice versa.
311 // Note: The current scheme may already work correctly for this case, I have not thought about this deeply
312 // and the case has not yet come up in practice. Alternatively, if not then this code can be removed
313 // aside from the assert false.
314 assertf( false, "Mangler_old should not visit typedecl: %s", toCString(decl));
315 assertf( decl->kind < TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->kind );
316 mangleName += Encoding::typeVariables[ decl->kind ] + std::to_string( decl->name.length() ) + decl->name;
317 }
318
319 __attribute__((unused)) void printVarMap( const std::map< std::string, std::pair< int, int > > &varMap, std::ostream &os ) {
320 for ( std::map< std::string, std::pair< int, int > >::const_iterator i = varMap.begin(); i != varMap.end(); ++i ) {
321 os << i->first << "(" << i->second.first << "/" << i->second.second << ")" << std::endl;
322 } // for
323 }
324
325 void Mangler_old::printQualifiers( const Type * type ) {
326 // skip if not including qualifiers
327 if ( typeMode ) return;
328 if ( ! type->forall.empty() ) {
329 std::list< std::string > assertionNames;
330 int dcount = 0, fcount = 0, vcount = 0, acount = 0;
331 mangleName += Encoding::forall;
332 for ( const TypeDecl * i : type->forall ) {
333 switch ( i->kind ) {
334 case TypeDecl::Dtype:
335 dcount++;
336 break;
337 case TypeDecl::Ftype:
338 fcount++;
339 break;
340 case TypeDecl::Ttype:
341 vcount++;
342 break;
343 default:
344 assertf( false, "unimplemented kind for type variable %s", SymTab::Mangler::Encoding::typeVariables[i->kind].c_str() );
345 } // switch
346 varNums[ i->name ] = std::make_pair( nextVarNum, (int)i->kind );
347 for ( const DeclarationWithType * assert : i->assertions ) {
348 PassVisitor<Mangler_old> sub_mangler(
349 mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums );
350 assert->accept( sub_mangler );
351 assertionNames.push_back( sub_mangler.pass.get_mangleName() );
352 acount++;
353 } // for
354 } // for
355 mangleName += std::to_string( dcount ) + "_" + std::to_string( fcount ) + "_" + std::to_string( vcount ) + "_" + std::to_string( acount ) + "_";
356 for(const auto & a : assertionNames) mangleName += a;
357// std::copy( assertionNames.begin(), assertionNames.end(), std::ostream_iterator< std::string >( mangleName, "" ) );
358 mangleName += "_";
359 } // if
360 if ( ! inFunctionType ) {
361 // these qualifiers do not distinguish the outermost type of a function parameter
362 if ( type->get_const() ) {
363 mangleName += Encoding::qualifiers.at(Type::Const);
364 } // if
365 if ( type->get_volatile() ) {
366 mangleName += Encoding::qualifiers.at(Type::Volatile);
367 } // if
368 // Removed due to restrict not affecting function compatibility in GCC
369 // if ( type->get_isRestrict() ) {
370 // mangleName += "E";
371 // } // if
372 if ( type->get_atomic() ) {
373 mangleName += Encoding::qualifiers.at(Type::Atomic);
374 } // if
375 }
376 if ( type->get_mutex() ) {
377 mangleName += Encoding::qualifiers.at(Type::Mutex);
378 } // if
379 if ( inFunctionType ) {
380 // turn off inFunctionType so that types can be differentiated for nested qualifiers
381 GuardValue( inFunctionType );
382 inFunctionType = false;
383 }
384 }
385 } // namespace
386 } // namespace Mangler
387} // namespace SymTab
388
389namespace Mangle {
390 namespace {
391 /// Mangles names to a unique C identifier
392 struct Mangler_new : public ast::WithShortCircuiting, public ast::WithVisitorRef<Mangler_new>, public ast::WithGuards {
393 Mangler_new( Mangle::Mode mode );
394 Mangler_new( const Mangler_new & ) = delete;
395
396 void previsit( const ast::Node * ) { visit_children = false; }
397
398 void postvisit( const ast::ObjectDecl * declaration );
399 void postvisit( const ast::FunctionDecl * declaration );
400 void postvisit( const ast::TypeDecl * declaration );
401
402 void postvisit( const ast::VoidType * voidType );
403 void postvisit( const ast::BasicType * basicType );
404 void postvisit( const ast::PointerType * pointerType );
405 void postvisit( const ast::ArrayType * arrayType );
406 void postvisit( const ast::ReferenceType * refType );
407 void postvisit( const ast::FunctionType * functionType );
408 void postvisit( const ast::StructInstType * aggregateUseType );
409 void postvisit( const ast::UnionInstType * aggregateUseType );
410 void postvisit( const ast::EnumInstType * aggregateUseType );
411 void postvisit( const ast::TypeInstType * aggregateUseType );
412 void postvisit( const ast::TraitInstType * inst );
413 void postvisit( const ast::TupleType * tupleType );
414 void postvisit( const ast::VarArgsType * varArgsType );
415 void postvisit( const ast::ZeroType * zeroType );
416 void postvisit( const ast::OneType * oneType );
417 void postvisit( const ast::QualifiedType * qualType );
418
419 /// The result is the current constructed mangled name.
420 std::string result() const { return mangleName; }
421 private:
422 std::string mangleName; ///< Mangled name being constructed
423 typedef std::map< std::string, std::pair< int, int > > VarMapType;
424 VarMapType varNums; ///< Map of type variables to indices
425 int nextVarNum; ///< Next type variable index
426 bool isTopLevel; ///< Is the Mangler at the top level
427 bool mangleOverridable; ///< Specially mangle overridable built-in methods
428 bool typeMode; ///< Produce a unique mangled name for a type
429 bool mangleGenericParams; ///< Include generic parameters in name mangling if true
430 bool inFunctionType = false; ///< Include type qualifiers if false.
431 bool inQualifiedType = false; ///< Add start/end delimiters around qualified type
432
433 private:
434 Mangler_new( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
435 int nextVarNum, const VarMapType& varNums );
436 friend class ast::Pass<Mangler_new>;
437
438 private:
439 void mangleDecl( const ast::DeclWithType *declaration );
440 void mangleRef( const ast::BaseInstType *refType, const std::string & prefix );
441
442 void printQualifiers( const ast::Type *type );
443 }; // Mangler_new
444 } // namespace
445
446 std::string mangle( const ast::Node * decl, Mangle::Mode mode ) {
447 return ast::Pass<Mangler_new>::read( decl, mode );
448 }
449
450 namespace {
451 Mangler_new::Mangler_new( Mangle::Mode mode )
452 : nextVarNum( 0 ), isTopLevel( true ),
453 mangleOverridable ( ! mode.no_overrideable ),
454 typeMode ( mode.type ),
455 mangleGenericParams( ! mode.no_generic_params ) {}
456
457 Mangler_new::Mangler_new( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
458 int nextVarNum, const VarMapType& varNums )
459 : varNums( varNums ), nextVarNum( nextVarNum ), isTopLevel( false ),
460 mangleOverridable( mangleOverridable ), typeMode( typeMode ),
461 mangleGenericParams( mangleGenericParams ) {}
462
463 void Mangler_new::mangleDecl( const ast::DeclWithType * decl ) {
464 bool wasTopLevel = isTopLevel;
465 if ( isTopLevel ) {
466 varNums.clear();
467 nextVarNum = 0;
468 isTopLevel = false;
469 } // if
470 mangleName += Encoding::manglePrefix;
471 const CodeGen::OperatorInfo * opInfo = CodeGen::operatorLookup( decl->name );
472 if ( opInfo ) {
473 mangleName += std::to_string( opInfo->outputName.size() ) + opInfo->outputName;
474 } else {
475 mangleName += std::to_string( decl->name.size() ) + decl->name;
476 } // if
477 decl->get_type()->accept( *visitor );
478 if ( mangleOverridable && decl->linkage.is_overrideable ) {
479 // want to be able to override autogenerated and intrinsic routines,
480 // so they need a different name mangling
481 if ( decl->linkage == ast::Linkage::AutoGen ) {
482 mangleName += Encoding::autogen;
483 } else if ( decl->linkage == ast::Linkage::Intrinsic ) {
484 mangleName += Encoding::intrinsic;
485 } else {
486 // if we add another kind of overridable function, this has to change
487 assert( false && "unknown overrideable linkage" );
488 } // if
489 }
490 isTopLevel = wasTopLevel;
491 }
492
493 void Mangler_new::postvisit( const ast::ObjectDecl * decl ) {
494 mangleDecl( decl );
495 }
496
497 void Mangler_new::postvisit( const ast::FunctionDecl * decl ) {
498 mangleDecl( decl );
499 }
500
501 void Mangler_new::postvisit( const ast::VoidType * voidType ) {
502 printQualifiers( voidType );
503 mangleName += Encoding::void_t;
504 }
505
506 void Mangler_new::postvisit( const ast::BasicType * basicType ) {
507 printQualifiers( basicType );
508 assertf( basicType->kind < ast::BasicType::NUMBER_OF_BASIC_TYPES, "Unhandled basic type: %d", basicType->kind );
509 mangleName += Encoding::basicTypes[ basicType->kind ];
510 }
511
512 void Mangler_new::postvisit( const ast::PointerType * pointerType ) {
513 printQualifiers( pointerType );
514 // mangle void (*f)() and void f() to the same name to prevent overloading on functions and function pointers
515 if ( ! pointerType->base.as<ast::FunctionType>() ) mangleName += Encoding::pointer;
516 maybe_accept( pointerType->base.get(), *visitor );
517 }
518
519 void Mangler_new::postvisit( const ast::ArrayType * arrayType ) {
520 // TODO: encode dimension
521 printQualifiers( arrayType );
522 mangleName += Encoding::array + "0";
523 arrayType->base->accept( *visitor );
524 }
525
526 void Mangler_new::postvisit( const ast::ReferenceType * refType ) {
527 // don't print prefix (e.g. 'R') for reference types so that references and non-references do not overload.
528 // Further, do not print the qualifiers for a reference type (but do run printQualifers because of TypeDecls, etc.),
529 // by pretending every reference type is a function parameter.
530 GuardValue( inFunctionType );
531 inFunctionType = true;
532 printQualifiers( refType );
533 refType->base->accept( *visitor );
534 }
535
536 void Mangler_new::postvisit( const ast::FunctionType * functionType ) {
537 printQualifiers( functionType );
538 mangleName += Encoding::function;
539 // turn on inFunctionType so that printQualifiers does not print most qualifiers for function parameters,
540 // since qualifiers on outermost parameter type do not differentiate function types, e.g.,
541 // void (*)(const int) and void (*)(int) are the same type, but void (*)(const int *) and void (*)(int *) are different
542 GuardValue( inFunctionType );
543 inFunctionType = true;
544 if (functionType->returns.empty()) mangleName += Encoding::void_t;
545 else accept_each( functionType->returns, *visitor );
546 mangleName += "_";
547 accept_each( functionType->params, *visitor );
548 mangleName += "_";
549 }
550
551 void Mangler_new::mangleRef(
552 const ast::BaseInstType * refType, const std::string & prefix ) {
553 printQualifiers( refType );
554
555 mangleName += prefix + std::to_string( refType->name.length() ) + refType->name;
556
557 if ( mangleGenericParams && ! refType->params.empty() ) {
558 mangleName += "_";
559 for ( const ast::Expr * param : refType->params ) {
560 auto paramType = dynamic_cast< const ast::TypeExpr * >( param );
561 assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString(param));
562 paramType->type->accept( *visitor );
563 }
564 mangleName += "_";
565 }
566 }
567
568 void Mangler_new::postvisit( const ast::StructInstType * aggregateUseType ) {
569 mangleRef( aggregateUseType, Encoding::struct_t );
570 }
571
572 void Mangler_new::postvisit( const ast::UnionInstType * aggregateUseType ) {
573 mangleRef( aggregateUseType, Encoding::union_t );
574 }
575
576 void Mangler_new::postvisit( const ast::EnumInstType * aggregateUseType ) {
577 mangleRef( aggregateUseType, Encoding::enum_t );
578 }
579
580 void Mangler_new::postvisit( const ast::TypeInstType * typeInst ) {
581 VarMapType::iterator varNum = varNums.find( typeInst->name );
582 if ( varNum == varNums.end() ) {
583 mangleRef( typeInst, Encoding::type );
584 } else {
585 printQualifiers( typeInst );
586 // Note: Can't use name here, since type variable names do not actually disambiguate a function, e.g.
587 // forall(dtype T) void f(T);
588 // forall(dtype S) void f(S);
589 // are equivalent and should mangle the same way. This is accomplished by numbering the type variables when they
590 // are first found and prefixing with the appropriate encoding for the type class.
591 assertf( varNum->second.second < ast::TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", varNum->second.second );
592 mangleName += Encoding::typeVariables[varNum->second.second] + std::to_string( varNum->second.first );
593 } // if
594 }
595
596 void Mangler_new::postvisit( const ast::TraitInstType * inst ) {
597 printQualifiers( inst );
598 mangleName += std::to_string( inst->name.size() ) + inst->name;
599 }
600
601 void Mangler_new::postvisit( const ast::TupleType * tupleType ) {
602 printQualifiers( tupleType );
603 mangleName += Encoding::tuple + std::to_string( tupleType->types.size() );
604 accept_each( tupleType->types, *visitor );
605 }
606
607 void Mangler_new::postvisit( const ast::VarArgsType * varArgsType ) {
608 printQualifiers( varArgsType );
609 static const std::string vargs = "__builtin_va_list";
610 mangleName += Encoding::type + std::to_string( vargs.size() ) + vargs;
611 }
612
613 void Mangler_new::postvisit( const ast::ZeroType * ) {
614 mangleName += Encoding::zero;
615 }
616
617 void Mangler_new::postvisit( const ast::OneType * ) {
618 mangleName += Encoding::one;
619 }
620
621 void Mangler_new::postvisit( const ast::QualifiedType * qualType ) {
622 bool inqual = inQualifiedType;
623 if ( !inqual ) {
624 // N marks the start of a qualified type
625 inQualifiedType = true;
626 mangleName += Encoding::qualifiedTypeStart;
627 }
628 qualType->parent->accept( *visitor );
629 qualType->child->accept( *visitor );
630 if ( !inqual ) {
631 // E marks the end of a qualified type
632 inQualifiedType = false;
633 mangleName += Encoding::qualifiedTypeEnd;
634 }
635 }
636
637 void Mangler_new::postvisit( const ast::TypeDecl * decl ) {
638 // TODO: is there any case where mangling a TypeDecl makes sense? If so, this code needs to be
639 // fixed to ensure that two TypeDecls mangle to the same name when they are the same type and vice versa.
640 // Note: The current scheme may already work correctly for this case, I have not thought about this deeply
641 // and the case has not yet come up in practice. Alternatively, if not then this code can be removed
642 // aside from the assert false.
643 assertf(false, "Mangler_new should not visit typedecl: %s", toCString(decl));
644 assertf( decl->kind < ast::TypeDecl::Kind::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->kind );
645 mangleName += Encoding::typeVariables[ decl->kind ] + std::to_string( decl->name.length() ) + decl->name;
646 }
647
648 // For debugging:
649 __attribute__((unused)) void printVarMap( const std::map< std::string, std::pair< int, int > > &varMap, std::ostream &os ) {
650 for ( std::map< std::string, std::pair< int, int > >::const_iterator i = varMap.begin(); i != varMap.end(); ++i ) {
651 os << i->first << "(" << i->second.first << "/" << i->second.second << ")" << std::endl;
652 } // for
653 }
654
655 void Mangler_new::printQualifiers( const ast::Type * type ) {
656 // skip if not including qualifiers
657 if ( typeMode ) return;
658 auto funcType = dynamic_cast<const ast::FunctionType *>( type );
659 if ( funcType && !funcType->forall.empty() ) {
660 std::list< std::string > assertionNames;
661 int dcount = 0, fcount = 0, vcount = 0, acount = 0;
662 mangleName += Encoding::forall;
663 for ( auto & decl : funcType->forall ) {
664 switch ( decl->kind ) {
665 case ast::TypeDecl::Dtype:
666 dcount++;
667 break;
668 case ast::TypeDecl::Ftype:
669 fcount++;
670 break;
671 case ast::TypeDecl::Ttype:
672 vcount++;
673 break;
674 default:
675 assertf( false, "unimplemented kind for type variable %s", SymTab::Mangler::Encoding::typeVariables[decl->kind].c_str() );
676 } // switch
677 varNums[ decl->name ] = std::make_pair( nextVarNum, (int)decl->kind );
678 } // for
679 for ( auto & assert : funcType->assertions ) {
680 assertionNames.push_back( ast::Pass<Mangler_new>::read(
681 assert->var.get(),
682 mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums ) );
683 acount++;
684 } // for
685 mangleName += std::to_string( dcount ) + "_" + std::to_string( fcount ) + "_" + std::to_string( vcount ) + "_" + std::to_string( acount ) + "_";
686 for ( const auto & a : assertionNames ) mangleName += a;
687 mangleName += "_";
688 } // if
689 if ( ! inFunctionType ) {
690 // these qualifiers do not distinguish the outermost type of a function parameter
691 if ( type->is_const() ) {
692 mangleName += Encoding::qualifiers.at( ast::CV::Const );
693 } // if
694 if ( type->is_volatile() ) {
695 mangleName += Encoding::qualifiers.at( ast::CV::Volatile );
696 } // if
697 // Removed due to restrict not affecting function compatibility in GCC
698 // if ( type->get_isRestrict() ) {
699 // mangleName += "E";
700 // } // if
701 if ( type->is_atomic() ) {
702 mangleName += Encoding::qualifiers.at( ast::CV::Atomic );
703 } // if
704 }
705 if ( type->is_mutex() ) {
706 mangleName += Encoding::qualifiers.at( ast::CV::Mutex );
707 } // if
708 if ( inFunctionType ) {
709 // turn off inFunctionType so that types can be differentiated for nested qualifiers
710 GuardValue( inFunctionType );
711 inFunctionType = false;
712 }
713 }
714 } // namespace
715} // namespace Mangle
716
717// Local Variables: //
718// tab-width: 4 //
719// mode: c++ //
720// compile-command: "make install" //
721// End: //
Note: See TracBrowser for help on using the repository browser.