source: src/SymTab/Mangler.cc@ be5f0a5

ADT ast-experimental
Last change on this file since be5f0a5 was 0026d67, checked in by Andrew Beach <ajbeach@…>, 3 years ago

Replaced Mangle::typeMode() with Mangle::mangleType(...), as it is how typeMode() was always used and it is shorter. Various other clean-up in the Mangler files.

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