source: src/SymTab/Mangler.cc@ 77125cc

ADT ast-experimental
Last change on this file since 77125cc was b0d9ff7, checked in by JiadaL <j82liang@…>, 3 years ago

Fix up the QualifiedNameExpr. It should now work on both old AST and new AST. There are some known bugs to fix so make all-tests will fail.

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