source: src/SymTab/Mangler.cpp@ bf4fe05

Last change on this file since bf4fe05 was c92bdcc, checked in by Andrew Beach <ajbeach@…>, 17 months ago

Updated the rest of the names in src/ (except for the generated files).

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