source: src/SymTab/Mangler.cc@ 45a091b

stuck-waitfor-destruct
Last change on this file since 45a091b was 0bd3faf, checked in by Andrew Beach <ajbeach@…>, 3 years ago

Removed forward declarations missed in the BaseSyntaxNode removal. Removed code and modified names to support two versions of the ast.

  • Property mode set to 100644
File size: 14.5 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
[9feb34b]26#include "Common/ToString.hpp" // for toCString
[ff5caaf]27#include "Common/SemanticError.h" // for SemanticError
[0dd3a2f]28
[d76c588]29namespace Mangle {
[1867c96]30 namespace {
31 /// Mangles names to a unique C identifier
[0bd3faf]32 struct Mangler : public ast::WithShortCircuiting, public ast::WithVisitorRef<Mangler>, public ast::WithGuards {
33 Mangler( Mangle::Mode mode );
34 Mangler( const Mangler & ) = delete;
[1867c96]35
[1346914]36 void previsit( const ast::Node * ) { visit_children = false; }
37
38 void postvisit( const ast::ObjectDecl * declaration );
39 void postvisit( const ast::FunctionDecl * declaration );
40 void postvisit( const ast::TypeDecl * declaration );
41
42 void postvisit( const ast::VoidType * voidType );
43 void postvisit( const ast::BasicType * basicType );
44 void postvisit( const ast::PointerType * pointerType );
45 void postvisit( const ast::ArrayType * arrayType );
46 void postvisit( const ast::ReferenceType * refType );
47 void postvisit( const ast::FunctionType * functionType );
48 void postvisit( const ast::StructInstType * aggregateUseType );
49 void postvisit( const ast::UnionInstType * aggregateUseType );
50 void postvisit( const ast::EnumInstType * aggregateUseType );
51 void postvisit( const ast::TypeInstType * aggregateUseType );
52 void postvisit( const ast::TraitInstType * inst );
53 void postvisit( const ast::TupleType * tupleType );
54 void postvisit( const ast::VarArgsType * varArgsType );
55 void postvisit( const ast::ZeroType * zeroType );
56 void postvisit( const ast::OneType * oneType );
57 void postvisit( const ast::QualifiedType * qualType );
[1867c96]58
[0026d67]59 /// The result is the current constructed mangled name.
60 std::string result() const { return mangleName; }
[1867c96]61 private:
[22b5b87]62 std::string mangleName; ///< Mangled name being constructed
[1867c96]63 typedef std::map< std::string, std::pair< int, int > > VarMapType;
64 VarMapType varNums; ///< Map of type variables to indices
65 int nextVarNum; ///< Next type variable index
66 bool isTopLevel; ///< Is the Mangler at the top level
67 bool mangleOverridable; ///< Specially mangle overridable built-in methods
68 bool typeMode; ///< Produce a unique mangled name for a type
69 bool mangleGenericParams; ///< Include generic parameters in name mangling if true
70 bool inFunctionType = false; ///< Include type qualifiers if false.
71 bool inQualifiedType = false; ///< Add start/end delimiters around qualified type
72
73 private:
[0bd3faf]74 Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
[1867c96]75 int nextVarNum, const VarMapType& varNums );
[0bd3faf]76 friend class ast::Pass<Mangler>;
[1867c96]77
78 private:
[1346914]79 void mangleDecl( const ast::DeclWithType *declaration );
[2c8c314]80 void mangleRef( const ast::BaseInstType *refType, const std::string & prefix );
[1867c96]81
[1346914]82 void printQualifiers( const ast::Type *type );
[0bd3faf]83 }; // Mangler
[1867c96]84 } // namespace
85
[d76c588]86 std::string mangle( const ast::Node * decl, Mangle::Mode mode ) {
[0bd3faf]87 return ast::Pass<Mangler>::read( decl, mode );
[d76c588]88 }
[1867c96]89
90 namespace {
[0bd3faf]91 Mangler::Mangler( Mangle::Mode mode )
[6f096d2]92 : nextVarNum( 0 ), isTopLevel( true ),
[1867c96]93 mangleOverridable ( ! mode.no_overrideable ),
[6f096d2]94 typeMode ( mode.type ),
[1867c96]95 mangleGenericParams( ! mode.no_generic_params ) {}
[6f096d2]96
[0bd3faf]97 Mangler::Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
[1867c96]98 int nextVarNum, const VarMapType& varNums )
[6f096d2]99 : varNums( varNums ), nextVarNum( nextVarNum ), isTopLevel( false ),
100 mangleOverridable( mangleOverridable ), typeMode( typeMode ),
[1867c96]101 mangleGenericParams( mangleGenericParams ) {}
102
[0bd3faf]103 void Mangler::mangleDecl( const ast::DeclWithType * decl ) {
[1867c96]104 bool wasTopLevel = isTopLevel;
105 if ( isTopLevel ) {
106 varNums.clear();
107 nextVarNum = 0;
108 isTopLevel = false;
109 } // if
[22b5b87]110 mangleName += Encoding::manglePrefix;
[60a8062]111 const CodeGen::OperatorInfo * opInfo = CodeGen::operatorLookup( decl->name );
112 if ( opInfo ) {
[22b5b87]113 mangleName += std::to_string( opInfo->outputName.size() ) + opInfo->outputName;
[1867c96]114 } else {
[22b5b87]115 mangleName += std::to_string( decl->name.size() ) + decl->name;
[1867c96]116 } // if
[a137d5a]117 decl->get_type()->accept( *visitor );
[1867c96]118 if ( mangleOverridable && decl->linkage.is_overrideable ) {
119 // want to be able to override autogenerated and intrinsic routines,
120 // so they need a different name mangling
121 if ( decl->linkage == ast::Linkage::AutoGen ) {
[22b5b87]122 mangleName += Encoding::autogen;
[1867c96]123 } else if ( decl->linkage == ast::Linkage::Intrinsic ) {
[22b5b87]124 mangleName += Encoding::intrinsic;
[1867c96]125 } else {
126 // if we add another kind of overridable function, this has to change
127 assert( false && "unknown overrideable linkage" );
128 } // if
129 }
130 isTopLevel = wasTopLevel;
131 }
132
[0bd3faf]133 void Mangler::postvisit( const ast::ObjectDecl * decl ) {
[1867c96]134 mangleDecl( decl );
135 }
136
[0bd3faf]137 void Mangler::postvisit( const ast::FunctionDecl * decl ) {
[1867c96]138 mangleDecl( decl );
139 }
140
[0bd3faf]141 void Mangler::postvisit( const ast::VoidType * voidType ) {
[1867c96]142 printQualifiers( voidType );
[22b5b87]143 mangleName += Encoding::void_t;
[1867c96]144 }
145
[0bd3faf]146 void Mangler::postvisit( const ast::BasicType * basicType ) {
[1867c96]147 printQualifiers( basicType );
148 assertf( basicType->kind < ast::BasicType::NUMBER_OF_BASIC_TYPES, "Unhandled basic type: %d", basicType->kind );
[22b5b87]149 mangleName += Encoding::basicTypes[ basicType->kind ];
[1867c96]150 }
151
[0bd3faf]152 void Mangler::postvisit( const ast::PointerType * pointerType ) {
[1867c96]153 printQualifiers( pointerType );
154 // mangle void (*f)() and void f() to the same name to prevent overloading on functions and function pointers
[22b5b87]155 if ( ! pointerType->base.as<ast::FunctionType>() ) mangleName += Encoding::pointer;
[1867c96]156 maybe_accept( pointerType->base.get(), *visitor );
157 }
158
[0bd3faf]159 void Mangler::postvisit( const ast::ArrayType * arrayType ) {
[1867c96]160 // TODO: encode dimension
161 printQualifiers( arrayType );
[22b5b87]162 mangleName += Encoding::array + "0";
[a137d5a]163 arrayType->base->accept( *visitor );
[1867c96]164 }
165
[0bd3faf]166 void Mangler::postvisit( const ast::ReferenceType * refType ) {
[1867c96]167 // don't print prefix (e.g. 'R') for reference types so that references and non-references do not overload.
168 // Further, do not print the qualifiers for a reference type (but do run printQualifers because of TypeDecls, etc.),
169 // by pretending every reference type is a function parameter.
170 GuardValue( inFunctionType );
171 inFunctionType = true;
172 printQualifiers( refType );
[a137d5a]173 refType->base->accept( *visitor );
[1867c96]174 }
175
[0bd3faf]176 void Mangler::postvisit( const ast::FunctionType * functionType ) {
[1867c96]177 printQualifiers( functionType );
[22b5b87]178 mangleName += Encoding::function;
[1867c96]179 // turn on inFunctionType so that printQualifiers does not print most qualifiers for function parameters,
180 // since qualifiers on outermost parameter type do not differentiate function types, e.g.,
181 // void (*)(const int) and void (*)(int) are the same type, but void (*)(const int *) and void (*)(int *) are different
182 GuardValue( inFunctionType );
183 inFunctionType = true;
[22b5b87]184 if (functionType->returns.empty()) mangleName += Encoding::void_t;
[954c954]185 else accept_each( functionType->returns, *visitor );
[22b5b87]186 mangleName += "_";
[954c954]187 accept_each( functionType->params, *visitor );
[22b5b87]188 mangleName += "_";
[1867c96]189 }
190
[0bd3faf]191 void Mangler::mangleRef(
[2c8c314]192 const ast::BaseInstType * refType, const std::string & prefix ) {
[1867c96]193 printQualifiers( refType );
194
[22b5b87]195 mangleName += prefix + std::to_string( refType->name.length() ) + refType->name;
[1867c96]196
[2c8c314]197 if ( mangleGenericParams && ! refType->params.empty() ) {
198 mangleName += "_";
199 for ( const ast::Expr * param : refType->params ) {
200 auto paramType = dynamic_cast< const ast::TypeExpr * >( param );
201 assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString(param));
[a137d5a]202 paramType->type->accept( *visitor );
[1867c96]203 }
[2c8c314]204 mangleName += "_";
[1867c96]205 }
206 }
207
[0bd3faf]208 void Mangler::postvisit( const ast::StructInstType * aggregateUseType ) {
[1867c96]209 mangleRef( aggregateUseType, Encoding::struct_t );
210 }
211
[0bd3faf]212 void Mangler::postvisit( const ast::UnionInstType * aggregateUseType ) {
[1867c96]213 mangleRef( aggregateUseType, Encoding::union_t );
214 }
215
[0bd3faf]216 void Mangler::postvisit( const ast::EnumInstType * aggregateUseType ) {
[1867c96]217 mangleRef( aggregateUseType, Encoding::enum_t );
218 }
219
[0bd3faf]220 void Mangler::postvisit( const ast::TypeInstType * typeInst ) {
[1867c96]221 VarMapType::iterator varNum = varNums.find( typeInst->name );
222 if ( varNum == varNums.end() ) {
223 mangleRef( typeInst, Encoding::type );
224 } else {
225 printQualifiers( typeInst );
226 // Note: Can't use name here, since type variable names do not actually disambiguate a function, e.g.
227 // forall(dtype T) void f(T);
228 // forall(dtype S) void f(S);
229 // are equivalent and should mangle the same way. This is accomplished by numbering the type variables when they
230 // are first found and prefixing with the appropriate encoding for the type class.
[a137d5a]231 assertf( varNum->second.second < ast::TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", varNum->second.second );
[22b5b87]232 mangleName += Encoding::typeVariables[varNum->second.second] + std::to_string( varNum->second.first );
[1867c96]233 } // if
234 }
235
[0bd3faf]236 void Mangler::postvisit( const ast::TraitInstType * inst ) {
[1867c96]237 printQualifiers( inst );
[22b5b87]238 mangleName += std::to_string( inst->name.size() ) + inst->name;
[1867c96]239 }
240
[0bd3faf]241 void Mangler::postvisit( const ast::TupleType * tupleType ) {
[1867c96]242 printQualifiers( tupleType );
[22b5b87]243 mangleName += Encoding::tuple + std::to_string( tupleType->types.size() );
[1346914]244 accept_each( tupleType->types, *visitor );
[1867c96]245 }
246
[0bd3faf]247 void Mangler::postvisit( const ast::VarArgsType * varArgsType ) {
[1867c96]248 printQualifiers( varArgsType );
249 static const std::string vargs = "__builtin_va_list";
[22b5b87]250 mangleName += Encoding::type + std::to_string( vargs.size() ) + vargs;
[1867c96]251 }
252
[0bd3faf]253 void Mangler::postvisit( const ast::ZeroType * ) {
[22b5b87]254 mangleName += Encoding::zero;
[1867c96]255 }
256
[0bd3faf]257 void Mangler::postvisit( const ast::OneType * ) {
[22b5b87]258 mangleName += Encoding::one;
[1867c96]259 }
260
[0bd3faf]261 void Mangler::postvisit( const ast::QualifiedType * qualType ) {
[1867c96]262 bool inqual = inQualifiedType;
[a137d5a]263 if ( !inqual ) {
[1867c96]264 // N marks the start of a qualified type
265 inQualifiedType = true;
[22b5b87]266 mangleName += Encoding::qualifiedTypeStart;
[1867c96]267 }
[a137d5a]268 qualType->parent->accept( *visitor );
269 qualType->child->accept( *visitor );
270 if ( !inqual ) {
[1867c96]271 // E marks the end of a qualified type
272 inQualifiedType = false;
[22b5b87]273 mangleName += Encoding::qualifiedTypeEnd;
[1867c96]274 }
275 }
276
[0bd3faf]277 void Mangler::postvisit( const ast::TypeDecl * decl ) {
[1867c96]278 // TODO: is there any case where mangling a TypeDecl makes sense? If so, this code needs to be
279 // fixed to ensure that two TypeDecls mangle to the same name when they are the same type and vice versa.
280 // Note: The current scheme may already work correctly for this case, I have not thought about this deeply
281 // and the case has not yet come up in practice. Alternatively, if not then this code can be removed
282 // aside from the assert false.
[0bd3faf]283 assertf(false, "Mangler should not visit typedecl: %s", toCString(decl));
[07de76b]284 assertf( decl->kind < ast::TypeDecl::Kind::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->kind );
[22b5b87]285 mangleName += Encoding::typeVariables[ decl->kind ] + std::to_string( decl->name.length() ) + decl->name;
[1867c96]286 }
287
[2c8c314]288 // For debugging:
[1867c96]289 __attribute__((unused)) void printVarMap( const std::map< std::string, std::pair< int, int > > &varMap, std::ostream &os ) {
290 for ( std::map< std::string, std::pair< int, int > >::const_iterator i = varMap.begin(); i != varMap.end(); ++i ) {
291 os << i->first << "(" << i->second.first << "/" << i->second.second << ")" << std::endl;
292 } // for
293 }
294
[0bd3faf]295 void Mangler::printQualifiers( const ast::Type * type ) {
[1867c96]296 // skip if not including qualifiers
297 if ( typeMode ) return;
[2c8c314]298 auto funcType = dynamic_cast<const ast::FunctionType *>( type );
299 if ( funcType && !funcType->forall.empty() ) {
300 std::list< std::string > assertionNames;
301 int dcount = 0, fcount = 0, vcount = 0, acount = 0;
302 mangleName += Encoding::forall;
303 for ( auto & decl : funcType->forall ) {
304 switch ( decl->kind ) {
305 case ast::TypeDecl::Dtype:
306 dcount++;
307 break;
308 case ast::TypeDecl::Ftype:
309 fcount++;
310 break;
311 case ast::TypeDecl::Ttype:
312 vcount++;
313 break;
314 default:
315 assertf( false, "unimplemented kind for type variable %s", SymTab::Mangler::Encoding::typeVariables[decl->kind].c_str() );
316 } // switch
317 varNums[ decl->name ] = std::make_pair( nextVarNum, (int)decl->kind );
318 } // for
319 for ( auto & assert : funcType->assertions ) {
[0bd3faf]320 assertionNames.push_back( ast::Pass<Mangler>::read(
[2c8c314]321 assert->var.get(),
322 mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums ) );
323 acount++;
324 } // for
325 mangleName += std::to_string( dcount ) + "_" + std::to_string( fcount ) + "_" + std::to_string( vcount ) + "_" + std::to_string( acount ) + "_";
326 for ( const auto & a : assertionNames ) mangleName += a;
327 mangleName += "_";
[1867c96]328 } // if
329 if ( ! inFunctionType ) {
330 // these qualifiers do not distinguish the outermost type of a function parameter
331 if ( type->is_const() ) {
[a137d5a]332 mangleName += Encoding::qualifiers.at( ast::CV::Const );
[1867c96]333 } // if
334 if ( type->is_volatile() ) {
[a137d5a]335 mangleName += Encoding::qualifiers.at( ast::CV::Volatile );
[1867c96]336 } // if
337 // Removed due to restrict not affecting function compatibility in GCC
338 // if ( type->get_isRestrict() ) {
[22b5b87]339 // mangleName += "E";
[1867c96]340 // } // if
341 if ( type->is_atomic() ) {
[a137d5a]342 mangleName += Encoding::qualifiers.at( ast::CV::Atomic );
[1867c96]343 } // if
344 }
345 if ( type->is_mutex() ) {
[a137d5a]346 mangleName += Encoding::qualifiers.at( ast::CV::Mutex );
[1867c96]347 } // if
348 if ( inFunctionType ) {
349 // turn off inFunctionType so that types can be differentiated for nested qualifiers
350 GuardValue( inFunctionType );
351 inFunctionType = false;
352 }
353 }
354 } // namespace
[d76c588]355} // namespace Mangle
356
[0dd3a2f]357// Local Variables: //
358// tab-width: 4 //
359// mode: c++ //
360// compile-command: "make install" //
361// End: //
Note: See TracBrowser for help on using the repository browser.