source: src/SymTab/Mangler.cc@ 8655363

Last change on this file since 8655363 was 8984003, checked in by Andrew Beach <ajbeach@…>, 22 months ago

Round of significant clean-up and reindentation of InitTweak directory.

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