source: src/SymTab/Mangler.cc@ 1ccae59

Last change on this file since 1ccae59 was 0bd3faf, checked in by Andrew Beach <ajbeach@…>, 23 months 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
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 namespace {
31 /// Mangles names to a unique C identifier
32 struct Mangler : public ast::WithShortCircuiting, public ast::WithVisitorRef<Mangler>, public ast::WithGuards {
33 Mangler( Mangle::Mode mode );
34 Mangler( const Mangler & ) = delete;
35
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 );
58
59 /// The result is the current constructed mangled name.
60 std::string result() const { return mangleName; }
61 private:
62 std::string mangleName; ///< Mangled name being constructed
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:
74 Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
75 int nextVarNum, const VarMapType& varNums );
76 friend class ast::Pass<Mangler>;
77
78 private:
79 void mangleDecl( const ast::DeclWithType *declaration );
80 void mangleRef( const ast::BaseInstType *refType, const std::string & prefix );
81
82 void printQualifiers( const ast::Type *type );
83 }; // Mangler
84 } // namespace
85
86 std::string mangle( const ast::Node * decl, Mangle::Mode mode ) {
87 return ast::Pass<Mangler>::read( decl, mode );
88 }
89
90 namespace {
91 Mangler::Mangler( Mangle::Mode mode )
92 : nextVarNum( 0 ), isTopLevel( true ),
93 mangleOverridable ( ! mode.no_overrideable ),
94 typeMode ( mode.type ),
95 mangleGenericParams( ! mode.no_generic_params ) {}
96
97 Mangler::Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
98 int nextVarNum, const VarMapType& varNums )
99 : varNums( varNums ), nextVarNum( nextVarNum ), isTopLevel( false ),
100 mangleOverridable( mangleOverridable ), typeMode( typeMode ),
101 mangleGenericParams( mangleGenericParams ) {}
102
103 void Mangler::mangleDecl( const ast::DeclWithType * decl ) {
104 bool wasTopLevel = isTopLevel;
105 if ( isTopLevel ) {
106 varNums.clear();
107 nextVarNum = 0;
108 isTopLevel = false;
109 } // if
110 mangleName += Encoding::manglePrefix;
111 const CodeGen::OperatorInfo * opInfo = CodeGen::operatorLookup( decl->name );
112 if ( opInfo ) {
113 mangleName += std::to_string( opInfo->outputName.size() ) + opInfo->outputName;
114 } else {
115 mangleName += std::to_string( decl->name.size() ) + decl->name;
116 } // if
117 decl->get_type()->accept( *visitor );
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 ) {
122 mangleName += Encoding::autogen;
123 } else if ( decl->linkage == ast::Linkage::Intrinsic ) {
124 mangleName += Encoding::intrinsic;
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
133 void Mangler::postvisit( const ast::ObjectDecl * decl ) {
134 mangleDecl( decl );
135 }
136
137 void Mangler::postvisit( const ast::FunctionDecl * decl ) {
138 mangleDecl( decl );
139 }
140
141 void Mangler::postvisit( const ast::VoidType * voidType ) {
142 printQualifiers( voidType );
143 mangleName += Encoding::void_t;
144 }
145
146 void Mangler::postvisit( const ast::BasicType * basicType ) {
147 printQualifiers( basicType );
148 assertf( basicType->kind < ast::BasicType::NUMBER_OF_BASIC_TYPES, "Unhandled basic type: %d", basicType->kind );
149 mangleName += Encoding::basicTypes[ basicType->kind ];
150 }
151
152 void Mangler::postvisit( const ast::PointerType * pointerType ) {
153 printQualifiers( pointerType );
154 // mangle void (*f)() and void f() to the same name to prevent overloading on functions and function pointers
155 if ( ! pointerType->base.as<ast::FunctionType>() ) mangleName += Encoding::pointer;
156 maybe_accept( pointerType->base.get(), *visitor );
157 }
158
159 void Mangler::postvisit( const ast::ArrayType * arrayType ) {
160 // TODO: encode dimension
161 printQualifiers( arrayType );
162 mangleName += Encoding::array + "0";
163 arrayType->base->accept( *visitor );
164 }
165
166 void Mangler::postvisit( const ast::ReferenceType * refType ) {
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 );
173 refType->base->accept( *visitor );
174 }
175
176 void Mangler::postvisit( const ast::FunctionType * functionType ) {
177 printQualifiers( functionType );
178 mangleName += Encoding::function;
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;
184 if (functionType->returns.empty()) mangleName += Encoding::void_t;
185 else accept_each( functionType->returns, *visitor );
186 mangleName += "_";
187 accept_each( functionType->params, *visitor );
188 mangleName += "_";
189 }
190
191 void Mangler::mangleRef(
192 const ast::BaseInstType * refType, const std::string & prefix ) {
193 printQualifiers( refType );
194
195 mangleName += prefix + std::to_string( refType->name.length() ) + refType->name;
196
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));
202 paramType->type->accept( *visitor );
203 }
204 mangleName += "_";
205 }
206 }
207
208 void Mangler::postvisit( const ast::StructInstType * aggregateUseType ) {
209 mangleRef( aggregateUseType, Encoding::struct_t );
210 }
211
212 void Mangler::postvisit( const ast::UnionInstType * aggregateUseType ) {
213 mangleRef( aggregateUseType, Encoding::union_t );
214 }
215
216 void Mangler::postvisit( const ast::EnumInstType * aggregateUseType ) {
217 mangleRef( aggregateUseType, Encoding::enum_t );
218 }
219
220 void Mangler::postvisit( const ast::TypeInstType * typeInst ) {
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.
231 assertf( varNum->second.second < ast::TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", varNum->second.second );
232 mangleName += Encoding::typeVariables[varNum->second.second] + std::to_string( varNum->second.first );
233 } // if
234 }
235
236 void Mangler::postvisit( const ast::TraitInstType * inst ) {
237 printQualifiers( inst );
238 mangleName += std::to_string( inst->name.size() ) + inst->name;
239 }
240
241 void Mangler::postvisit( const ast::TupleType * tupleType ) {
242 printQualifiers( tupleType );
243 mangleName += Encoding::tuple + std::to_string( tupleType->types.size() );
244 accept_each( tupleType->types, *visitor );
245 }
246
247 void Mangler::postvisit( const ast::VarArgsType * varArgsType ) {
248 printQualifiers( varArgsType );
249 static const std::string vargs = "__builtin_va_list";
250 mangleName += Encoding::type + std::to_string( vargs.size() ) + vargs;
251 }
252
253 void Mangler::postvisit( const ast::ZeroType * ) {
254 mangleName += Encoding::zero;
255 }
256
257 void Mangler::postvisit( const ast::OneType * ) {
258 mangleName += Encoding::one;
259 }
260
261 void Mangler::postvisit( const ast::QualifiedType * qualType ) {
262 bool inqual = inQualifiedType;
263 if ( !inqual ) {
264 // N marks the start of a qualified type
265 inQualifiedType = true;
266 mangleName += Encoding::qualifiedTypeStart;
267 }
268 qualType->parent->accept( *visitor );
269 qualType->child->accept( *visitor );
270 if ( !inqual ) {
271 // E marks the end of a qualified type
272 inQualifiedType = false;
273 mangleName += Encoding::qualifiedTypeEnd;
274 }
275 }
276
277 void Mangler::postvisit( const ast::TypeDecl * decl ) {
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.
283 assertf(false, "Mangler should not visit typedecl: %s", toCString(decl));
284 assertf( decl->kind < ast::TypeDecl::Kind::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->kind );
285 mangleName += Encoding::typeVariables[ decl->kind ] + std::to_string( decl->name.length() ) + decl->name;
286 }
287
288 // For debugging:
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
295 void Mangler::printQualifiers( const ast::Type * type ) {
296 // skip if not including qualifiers
297 if ( typeMode ) return;
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 ) {
320 assertionNames.push_back( ast::Pass<Mangler>::read(
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 += "_";
328 } // if
329 if ( ! inFunctionType ) {
330 // these qualifiers do not distinguish the outermost type of a function parameter
331 if ( type->is_const() ) {
332 mangleName += Encoding::qualifiers.at( ast::CV::Const );
333 } // if
334 if ( type->is_volatile() ) {
335 mangleName += Encoding::qualifiers.at( ast::CV::Volatile );
336 } // if
337 // Removed due to restrict not affecting function compatibility in GCC
338 // if ( type->get_isRestrict() ) {
339 // mangleName += "E";
340 // } // if
341 if ( type->is_atomic() ) {
342 mangleName += Encoding::qualifiers.at( ast::CV::Atomic );
343 } // if
344 }
345 if ( type->is_mutex() ) {
346 mangleName += Encoding::qualifiers.at( ast::CV::Mutex );
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
355} // namespace Mangle
356
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.