source: src/SymTab/Mangler.cc@ 6b419ce

Last change on this file since 6b419ce 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
RevLine 
[0dd3a2f]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//
[8c49c0e]7// Mangler.cc --
[0dd3a2f]8//
9// Author : Richard C. Bilson
10// Created On : Sun May 17 21:40:29 2015
[0026d67]11// Last Modified By : Andrew Beach
12// Last Modified On : Fri Oct 21 16:18:00 2022
13// Update Count : 75
[0dd3a2f]14//
[30f9072]15#include "Mangler.h"
[0dd3a2f]16
[ff5caaf]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
[a137d5a]24#include "AST/Pass.hpp"
[ff5caaf]25#include "CodeGen/OperatorTable.h" // for OperatorInfo, operatorLookup
[d7d9a60]26#include "Common/PassVisitor.h"
[9feb34b]27#include "Common/ToString.hpp" // for toCString
[ff5caaf]28#include "Common/SemanticError.h" // for SemanticError
29#include "ResolvExpr/TypeEnvironment.h" // for TypeEnvironment
[07de76b]30#include "SynTree/LinkageSpec.h" // for Spec, isOverridable, AutoGen, Int...
[ff5caaf]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...
[51b73452]34
35namespace SymTab {
[d7d9a60]36 namespace Mangler {
37 namespace {
38 /// Mangles names to a unique C identifier
[1867c96]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;
[d7d9a60]42
[6f096d2]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 );
[d7d9a60]65
[22b5b87]66 std::string get_mangleName() { return mangleName; }
[d7d9a60]67 private:
[22b5b87]68 std::string mangleName; ///< Mangled name being constructed
[052cd71]69 typedef std::map< std::string, std::pair< int, int > > VarMapType;
[d7d9a60]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
[c0453ca3]76 bool inFunctionType = false; ///< Include type qualifiers if false.
[642bc83]77 bool inQualifiedType = false; ///< Add start/end delimiters around qualified type
[d7d9a60]78
[e1f7eef]79 public:
[6f096d2]80 Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
[052cd71]81 int nextVarNum, const VarMapType& varNums );
[ff5caaf]82
[e1f7eef]83 private:
[6f096d2]84 void mangleDecl( const DeclarationWithType * declaration );
85 void mangleRef( const ReferenceToType * refType, std::string prefix );
[d7d9a60]86
[6f096d2]87 void printQualifiers( const Type *type );
[1867c96]88 }; // Mangler_old
[d7d9a60]89 } // namespace
90
[6f096d2]91 std::string mangle( const BaseSyntaxNode * decl, bool mangleOverridable, bool typeMode, bool mangleGenericParams ) {
[1867c96]92 PassVisitor<Mangler_old> mangler( mangleOverridable, typeMode, mangleGenericParams );
[d7d9a60]93 maybeAccept( decl, mangler );
94 return mangler.pass.get_mangleName();
[4aa0858]95 }
[d7d9a60]96
[6f096d2]97 std::string mangleType( const Type * ty ) {
[1867c96]98 PassVisitor<Mangler_old> mangler( false, true, true );
[d7d9a60]99 maybeAccept( ty, mangler );
100 return mangler.pass.get_mangleName();
101 }
102
[6f096d2]103 std::string mangleConcrete( const Type * ty ) {
[1867c96]104 PassVisitor<Mangler_old> mangler( false, false, false );
[d7d9a60]105 maybeAccept( ty, mangler );
106 return mangler.pass.get_mangleName();
[0dd3a2f]107 }
[d7d9a60]108
109 namespace {
[1867c96]110 Mangler_old::Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams )
[6f096d2]111 : nextVarNum( 0 ), isTopLevel( true ),
112 mangleOverridable( mangleOverridable ), typeMode( typeMode ),
[ff5caaf]113 mangleGenericParams( mangleGenericParams ) {}
[6f096d2]114
115 Mangler_old::Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
[052cd71]116 int nextVarNum, const VarMapType& varNums )
[6f096d2]117 : varNums( varNums ), nextVarNum( nextVarNum ), isTopLevel( false ),
118 mangleOverridable( mangleOverridable ), typeMode( typeMode ),
[ff5caaf]119 mangleGenericParams( mangleGenericParams ) {}
[d7d9a60]120
[6f096d2]121 void Mangler_old::mangleDecl( const DeclarationWithType * declaration ) {
[d7d9a60]122 bool wasTopLevel = isTopLevel;
123 if ( isTopLevel ) {
124 varNums.clear();
125 nextVarNum = 0;
126 isTopLevel = false;
127 } // if
[22b5b87]128 mangleName += Encoding::manglePrefix;
[60a8062]129 const CodeGen::OperatorInfo * opInfo = CodeGen::operatorLookup( declaration->get_name() );
130 if ( opInfo ) {
[22b5b87]131 mangleName += std::to_string( opInfo->outputName.size() ) + opInfo->outputName;
[d7d9a60]132 } else {
[22b5b87]133 mangleName += std::to_string( declaration->name.size() ) + declaration->name;
[d7d9a60]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 ) {
[22b5b87]140 mangleName += Encoding::autogen;
[d7d9a60]141 } else if ( declaration->get_linkage() == LinkageSpec::Intrinsic ) {
[22b5b87]142 mangleName += Encoding::intrinsic;
[d7d9a60]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
[6f096d2]151 void Mangler_old::postvisit( const ObjectDecl * declaration ) {
[d7d9a60]152 mangleDecl( declaration );
153 }
154
[6f096d2]155 void Mangler_old::postvisit( const FunctionDecl * declaration ) {
[d7d9a60]156 mangleDecl( declaration );
157 }
158
[6f096d2]159 void Mangler_old::postvisit( const VoidType * voidType ) {
[d7d9a60]160 printQualifiers( voidType );
[22b5b87]161 mangleName += Encoding::void_t;
[d7d9a60]162 }
163
[6f096d2]164 void Mangler_old::postvisit( const BasicType * basicType ) {
[d7d9a60]165 printQualifiers( basicType );
[6f096d2]166 assertf( basicType->kind < BasicType::NUMBER_OF_BASIC_TYPES, "Unhandled basic type: %d", basicType->kind );
[22b5b87]167 mangleName += Encoding::basicTypes[ basicType->kind ];
[d7d9a60]168 }
169
[6f096d2]170 void Mangler_old::postvisit( const PointerType * pointerType ) {
[d7d9a60]171 printQualifiers( pointerType );
[3f024c9]172 // mangle void (*f)() and void f() to the same name to prevent overloading on functions and function pointers
[22b5b87]173 if ( ! dynamic_cast<FunctionType *>( pointerType->base ) ) mangleName += Encoding::pointer;
[1da22500]174 maybeAccept( pointerType->base, *visitor );
[d7d9a60]175 }
176
[6f096d2]177 void Mangler_old::postvisit( const ArrayType * arrayType ) {
[d7d9a60]178 // TODO: encode dimension
179 printQualifiers( arrayType );
[22b5b87]180 mangleName += Encoding::array + "0";
[1da22500]181 maybeAccept( arrayType->base, *visitor );
[d7d9a60]182 }
183
[6f096d2]184 void Mangler_old::postvisit( const ReferenceType * refType ) {
[c0453ca3]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;
[d7d9a60]190 printQualifiers( refType );
[1da22500]191 maybeAccept( refType->base, *visitor );
[d7d9a60]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
[6f096d2]203 void Mangler_old::postvisit( const FunctionType * functionType ) {
[d7d9a60]204 printQualifiers( functionType );
[22b5b87]205 mangleName += Encoding::function;
[c0453ca3]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;
[96812c0]211 std::list< Type* > returnTypes = getTypes( functionType->returnVals );
[22b5b87]212 if (returnTypes.empty()) mangleName += Encoding::void_t;
[d1e0979]213 else acceptAll( returnTypes, *visitor );
[22b5b87]214 mangleName += "_";
[96812c0]215 std::list< Type* > paramTypes = getTypes( functionType->parameters );
[d7d9a60]216 acceptAll( paramTypes, *visitor );
[22b5b87]217 mangleName += "_";
[d7d9a60]218 }
219
[6f096d2]220 void Mangler_old::mangleRef( const ReferenceToType * refType, std::string prefix ) {
[d7d9a60]221 printQualifiers( refType );
222
[22b5b87]223 mangleName += prefix + std::to_string( refType->name.length() ) + refType->name;
[d7d9a60]224
225 if ( mangleGenericParams ) {
[6f096d2]226 const std::list< Expression* > & params = refType->parameters;
[d7d9a60]227 if ( ! params.empty() ) {
[22b5b87]228 mangleName += "_";
[6f096d2]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));
[96812c0]232 maybeAccept( paramType->type, *visitor );
[d7d9a60]233 }
[22b5b87]234 mangleName += "_";
[d7d9a60]235 }
[e35f30a]236 }
[d7d9a60]237 }
238
[6f096d2]239 void Mangler_old::postvisit( const StructInstType * aggregateUseType ) {
[7804e2a]240 mangleRef( aggregateUseType, Encoding::struct_t );
[d7d9a60]241 }
242
[6f096d2]243 void Mangler_old::postvisit( const UnionInstType * aggregateUseType ) {
[7804e2a]244 mangleRef( aggregateUseType, Encoding::union_t );
[d7d9a60]245 }
246
[6f096d2]247 void Mangler_old::postvisit( const EnumInstType * aggregateUseType ) {
[7804e2a]248 mangleRef( aggregateUseType, Encoding::enum_t );
[d7d9a60]249 }
250
[6f096d2]251 void Mangler_old::postvisit( const TypeInstType * typeInst ) {
[d7d9a60]252 VarMapType::iterator varNum = varNums.find( typeInst->get_name() );
253 if ( varNum == varNums.end() ) {
[d8cb7df]254 mangleRef( typeInst, Encoding::type );
[d7d9a60]255 } else {
256 printQualifiers( typeInst );
[0e761e40]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.
[0e73845]262 assertf( varNum->second.second < TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", varNum->second.second );
[22b5b87]263 mangleName += Encoding::typeVariables[varNum->second.second] + std::to_string( varNum->second.first );
[d7d9a60]264 } // if
265 }
266
[6f096d2]267 void Mangler_old::postvisit( const TraitInstType * inst ) {
[f465f0e]268 printQualifiers( inst );
[22b5b87]269 mangleName += std::to_string( inst->name.size() ) + inst->name;
[f465f0e]270 }
271
[6f096d2]272 void Mangler_old::postvisit( const TupleType * tupleType ) {
[d7d9a60]273 printQualifiers( tupleType );
[22b5b87]274 mangleName += Encoding::tuple + std::to_string( tupleType->types.size() );
[d7d9a60]275 acceptAll( tupleType->types, *visitor );
[8360977]276 }
[d7d9a60]277
[6f096d2]278 void Mangler_old::postvisit( const VarArgsType * varArgsType ) {
[d7d9a60]279 printQualifiers( varArgsType );
[642bc83]280 static const std::string vargs = "__builtin_va_list";
[22b5b87]281 mangleName += Encoding::type + std::to_string( vargs.size() ) + vargs;
[d7d9a60]282 }
283
[6f096d2]284 void Mangler_old::postvisit( const ZeroType * ) {
[22b5b87]285 mangleName += Encoding::zero;
[d7d9a60]286 }
287
[6f096d2]288 void Mangler_old::postvisit( const OneType * ) {
[22b5b87]289 mangleName += Encoding::one;
[d7d9a60]290 }
291
[6f096d2]292 void Mangler_old::postvisit( const QualifiedType * qualType ) {
[642bc83]293 bool inqual = inQualifiedType;
294 if (! inqual ) {
295 // N marks the start of a qualified type
296 inQualifiedType = true;
[22b5b87]297 mangleName += Encoding::qualifiedTypeStart;
[642bc83]298 }
[e73becf]299 maybeAccept( qualType->parent, *visitor );
300 maybeAccept( qualType->child, *visitor );
[642bc83]301 if ( ! inqual ) {
302 // E marks the end of a qualified type
303 inQualifiedType = false;
[22b5b87]304 mangleName += Encoding::qualifiedTypeEnd;
[642bc83]305 }
[e73becf]306 }
307
[6f096d2]308 void Mangler_old::postvisit( const TypeDecl * decl ) {
[0e761e40]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.
[b66d14a]314 assertf( false, "Mangler_old should not visit typedecl: %s", toCString(decl));
[6f096d2]315 assertf( decl->kind < TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->kind );
[22b5b87]316 mangleName += Encoding::typeVariables[ decl->kind ] + std::to_string( decl->name.length() ) + decl->name;
[d7d9a60]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;
[0dd3a2f]322 } // for
[d7d9a60]323 }
324
[6f096d2]325 void Mangler_old::printQualifiers( const Type * type ) {
[d7d9a60]326 // skip if not including qualifiers
327 if ( typeMode ) return;
[6f096d2]328 if ( ! type->forall.empty() ) {
[d7d9a60]329 std::list< std::string > assertionNames;
[0e73845]330 int dcount = 0, fcount = 0, vcount = 0, acount = 0;
[22b5b87]331 mangleName += Encoding::forall;
[6f096d2]332 for ( const TypeDecl * i : type->forall ) {
333 switch ( i->kind ) {
[d7d9a60]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:
[b66d14a]344 assertf( false, "unimplemented kind for type variable %s", SymTab::Mangler::Encoding::typeVariables[i->kind].c_str() );
[d7d9a60]345 } // switch
[6f096d2]346 varNums[ i->name ] = std::make_pair( nextVarNum, (int)i->kind );
347 for ( const DeclarationWithType * assert : i->assertions ) {
348 PassVisitor<Mangler_old> sub_mangler(
[052cd71]349 mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums );
[6f096d2]350 assert->accept( sub_mangler );
[ff5caaf]351 assertionNames.push_back( sub_mangler.pass.get_mangleName() );
[0e73845]352 acount++;
[d7d9a60]353 } // for
354 } // for
[22b5b87]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 += "_";
[d7d9a60]359 } // if
[c0453ca3]360 if ( ! inFunctionType ) {
361 // these qualifiers do not distinguish the outermost type of a function parameter
362 if ( type->get_const() ) {
[22b5b87]363 mangleName += Encoding::qualifiers.at(Type::Const);
[c0453ca3]364 } // if
365 if ( type->get_volatile() ) {
[22b5b87]366 mangleName += Encoding::qualifiers.at(Type::Volatile);
[c0453ca3]367 } // if
368 // Removed due to restrict not affecting function compatibility in GCC
369 // if ( type->get_isRestrict() ) {
[22b5b87]370 // mangleName += "E";
[c0453ca3]371 // } // if
372 if ( type->get_atomic() ) {
[22b5b87]373 mangleName += Encoding::qualifiers.at(Type::Atomic);
[c0453ca3]374 } // if
375 }
[d7d9a60]376 if ( type->get_mutex() ) {
[22b5b87]377 mangleName += Encoding::qualifiers.at(Type::Mutex);
[d7d9a60]378 } // if
[c0453ca3]379 if ( inFunctionType ) {
380 // turn off inFunctionType so that types can be differentiated for nested qualifiers
381 GuardValue( inFunctionType );
382 inFunctionType = false;
383 }
[d7d9a60]384 }
[22b5b87]385 } // namespace
[d7d9a60]386 } // namespace Mangler
[0dd3a2f]387} // namespace SymTab
388
[d76c588]389namespace Mangle {
[1867c96]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
[1346914]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 );
[1867c96]418
[0026d67]419 /// The result is the current constructed mangled name.
420 std::string result() const { return mangleName; }
[1867c96]421 private:
[22b5b87]422 std::string mangleName; ///< Mangled name being constructed
[1867c96]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:
[6f096d2]434 Mangler_new( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
[1867c96]435 int nextVarNum, const VarMapType& varNums );
436 friend class ast::Pass<Mangler_new>;
437
438 private:
[1346914]439 void mangleDecl( const ast::DeclWithType *declaration );
[2c8c314]440 void mangleRef( const ast::BaseInstType *refType, const std::string & prefix );
[1867c96]441
[1346914]442 void printQualifiers( const ast::Type *type );
[1867c96]443 }; // Mangler_new
444 } // namespace
445
[d76c588]446 std::string mangle( const ast::Node * decl, Mangle::Mode mode ) {
[0026d67]447 return ast::Pass<Mangler_new>::read( decl, mode );
[d76c588]448 }
[1867c96]449
450 namespace {
451 Mangler_new::Mangler_new( Mangle::Mode mode )
[6f096d2]452 : nextVarNum( 0 ), isTopLevel( true ),
[1867c96]453 mangleOverridable ( ! mode.no_overrideable ),
[6f096d2]454 typeMode ( mode.type ),
[1867c96]455 mangleGenericParams( ! mode.no_generic_params ) {}
[6f096d2]456
457 Mangler_new::Mangler_new( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
[1867c96]458 int nextVarNum, const VarMapType& varNums )
[6f096d2]459 : varNums( varNums ), nextVarNum( nextVarNum ), isTopLevel( false ),
460 mangleOverridable( mangleOverridable ), typeMode( typeMode ),
[1867c96]461 mangleGenericParams( mangleGenericParams ) {}
462
[1346914]463 void Mangler_new::mangleDecl( const ast::DeclWithType * decl ) {
[1867c96]464 bool wasTopLevel = isTopLevel;
465 if ( isTopLevel ) {
466 varNums.clear();
467 nextVarNum = 0;
468 isTopLevel = false;
469 } // if
[22b5b87]470 mangleName += Encoding::manglePrefix;
[60a8062]471 const CodeGen::OperatorInfo * opInfo = CodeGen::operatorLookup( decl->name );
472 if ( opInfo ) {
[22b5b87]473 mangleName += std::to_string( opInfo->outputName.size() ) + opInfo->outputName;
[1867c96]474 } else {
[22b5b87]475 mangleName += std::to_string( decl->name.size() ) + decl->name;
[1867c96]476 } // if
[a137d5a]477 decl->get_type()->accept( *visitor );
[1867c96]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 ) {
[22b5b87]482 mangleName += Encoding::autogen;
[1867c96]483 } else if ( decl->linkage == ast::Linkage::Intrinsic ) {
[22b5b87]484 mangleName += Encoding::intrinsic;
[1867c96]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
[1346914]493 void Mangler_new::postvisit( const ast::ObjectDecl * decl ) {
[1867c96]494 mangleDecl( decl );
495 }
496
[1346914]497 void Mangler_new::postvisit( const ast::FunctionDecl * decl ) {
[1867c96]498 mangleDecl( decl );
499 }
500
[1346914]501 void Mangler_new::postvisit( const ast::VoidType * voidType ) {
[1867c96]502 printQualifiers( voidType );
[22b5b87]503 mangleName += Encoding::void_t;
[1867c96]504 }
505
[1346914]506 void Mangler_new::postvisit( const ast::BasicType * basicType ) {
[1867c96]507 printQualifiers( basicType );
508 assertf( basicType->kind < ast::BasicType::NUMBER_OF_BASIC_TYPES, "Unhandled basic type: %d", basicType->kind );
[22b5b87]509 mangleName += Encoding::basicTypes[ basicType->kind ];
[1867c96]510 }
511
[1346914]512 void Mangler_new::postvisit( const ast::PointerType * pointerType ) {
[1867c96]513 printQualifiers( pointerType );
514 // mangle void (*f)() and void f() to the same name to prevent overloading on functions and function pointers
[22b5b87]515 if ( ! pointerType->base.as<ast::FunctionType>() ) mangleName += Encoding::pointer;
[1867c96]516 maybe_accept( pointerType->base.get(), *visitor );
517 }
518
[1346914]519 void Mangler_new::postvisit( const ast::ArrayType * arrayType ) {
[1867c96]520 // TODO: encode dimension
521 printQualifiers( arrayType );
[22b5b87]522 mangleName += Encoding::array + "0";
[a137d5a]523 arrayType->base->accept( *visitor );
[1867c96]524 }
525
[1346914]526 void Mangler_new::postvisit( const ast::ReferenceType * refType ) {
[1867c96]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 );
[a137d5a]533 refType->base->accept( *visitor );
[1867c96]534 }
535
[1346914]536 void Mangler_new::postvisit( const ast::FunctionType * functionType ) {
[1867c96]537 printQualifiers( functionType );
[22b5b87]538 mangleName += Encoding::function;
[1867c96]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;
[22b5b87]544 if (functionType->returns.empty()) mangleName += Encoding::void_t;
[954c954]545 else accept_each( functionType->returns, *visitor );
[22b5b87]546 mangleName += "_";
[954c954]547 accept_each( functionType->params, *visitor );
[22b5b87]548 mangleName += "_";
[1867c96]549 }
550
[2c8c314]551 void Mangler_new::mangleRef(
552 const ast::BaseInstType * refType, const std::string & prefix ) {
[1867c96]553 printQualifiers( refType );
554
[22b5b87]555 mangleName += prefix + std::to_string( refType->name.length() ) + refType->name;
[1867c96]556
[2c8c314]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));
[a137d5a]562 paramType->type->accept( *visitor );
[1867c96]563 }
[2c8c314]564 mangleName += "_";
[1867c96]565 }
566 }
567
[1346914]568 void Mangler_new::postvisit( const ast::StructInstType * aggregateUseType ) {
[1867c96]569 mangleRef( aggregateUseType, Encoding::struct_t );
570 }
571
[1346914]572 void Mangler_new::postvisit( const ast::UnionInstType * aggregateUseType ) {
[1867c96]573 mangleRef( aggregateUseType, Encoding::union_t );
574 }
575
[1346914]576 void Mangler_new::postvisit( const ast::EnumInstType * aggregateUseType ) {
[1867c96]577 mangleRef( aggregateUseType, Encoding::enum_t );
578 }
579
[1346914]580 void Mangler_new::postvisit( const ast::TypeInstType * typeInst ) {
[1867c96]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.
[a137d5a]591 assertf( varNum->second.second < ast::TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", varNum->second.second );
[22b5b87]592 mangleName += Encoding::typeVariables[varNum->second.second] + std::to_string( varNum->second.first );
[1867c96]593 } // if
594 }
595
[1346914]596 void Mangler_new::postvisit( const ast::TraitInstType * inst ) {
[1867c96]597 printQualifiers( inst );
[22b5b87]598 mangleName += std::to_string( inst->name.size() ) + inst->name;
[1867c96]599 }
600
[1346914]601 void Mangler_new::postvisit( const ast::TupleType * tupleType ) {
[1867c96]602 printQualifiers( tupleType );
[22b5b87]603 mangleName += Encoding::tuple + std::to_string( tupleType->types.size() );
[1346914]604 accept_each( tupleType->types, *visitor );
[1867c96]605 }
606
[1346914]607 void Mangler_new::postvisit( const ast::VarArgsType * varArgsType ) {
[1867c96]608 printQualifiers( varArgsType );
609 static const std::string vargs = "__builtin_va_list";
[22b5b87]610 mangleName += Encoding::type + std::to_string( vargs.size() ) + vargs;
[1867c96]611 }
612
[1346914]613 void Mangler_new::postvisit( const ast::ZeroType * ) {
[22b5b87]614 mangleName += Encoding::zero;
[1867c96]615 }
616
[1346914]617 void Mangler_new::postvisit( const ast::OneType * ) {
[22b5b87]618 mangleName += Encoding::one;
[1867c96]619 }
620
[1346914]621 void Mangler_new::postvisit( const ast::QualifiedType * qualType ) {
[1867c96]622 bool inqual = inQualifiedType;
[a137d5a]623 if ( !inqual ) {
[1867c96]624 // N marks the start of a qualified type
625 inQualifiedType = true;
[22b5b87]626 mangleName += Encoding::qualifiedTypeStart;
[1867c96]627 }
[a137d5a]628 qualType->parent->accept( *visitor );
629 qualType->child->accept( *visitor );
630 if ( !inqual ) {
[1867c96]631 // E marks the end of a qualified type
632 inQualifiedType = false;
[22b5b87]633 mangleName += Encoding::qualifiedTypeEnd;
[1867c96]634 }
635 }
636
[1346914]637 void Mangler_new::postvisit( const ast::TypeDecl * decl ) {
[1867c96]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));
[07de76b]644 assertf( decl->kind < ast::TypeDecl::Kind::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->kind );
[22b5b87]645 mangleName += Encoding::typeVariables[ decl->kind ] + std::to_string( decl->name.length() ) + decl->name;
[1867c96]646 }
647
[2c8c314]648 // For debugging:
[1867c96]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
[1346914]655 void Mangler_new::printQualifiers( const ast::Type * type ) {
[1867c96]656 // skip if not including qualifiers
657 if ( typeMode ) return;
[2c8c314]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 += "_";
[1867c96]688 } // if
689 if ( ! inFunctionType ) {
690 // these qualifiers do not distinguish the outermost type of a function parameter
691 if ( type->is_const() ) {
[a137d5a]692 mangleName += Encoding::qualifiers.at( ast::CV::Const );
[1867c96]693 } // if
694 if ( type->is_volatile() ) {
[a137d5a]695 mangleName += Encoding::qualifiers.at( ast::CV::Volatile );
[1867c96]696 } // if
697 // Removed due to restrict not affecting function compatibility in GCC
698 // if ( type->get_isRestrict() ) {
[22b5b87]699 // mangleName += "E";
[1867c96]700 // } // if
701 if ( type->is_atomic() ) {
[a137d5a]702 mangleName += Encoding::qualifiers.at( ast::CV::Atomic );
[1867c96]703 } // if
704 }
705 if ( type->is_mutex() ) {
[a137d5a]706 mangleName += Encoding::qualifiers.at( ast::CV::Mutex );
[1867c96]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
[d76c588]715} // namespace Mangle
716
[0dd3a2f]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.