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

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr persistent-indexer pthread-emulation qualifiedEnum
Last change on this file since 1b54b54 was e1f7eef, checked in by Aaron Moss <a3moss@…>, 7 years ago

Add type-environment cached deferred resolution

  • Property mode set to 100644
File size: 17.3 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 : Peter A. Buhr
12// Last Modified On : Mon Sep 25 15:49:26 2017
13// Update Count : 23
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 "CodeGen/OperatorTable.h" // for OperatorInfo, operatorLookup
25#include "Common/PassVisitor.h"
26#include "Common/SemanticError.h" // for SemanticError
27#include "Common/utility.h" // for toString
28#include "Parser/LinkageSpec.h" // for Spec, isOverridable, AutoGen, Int...
29#include "ResolvExpr/TypeEnvironment.h" // for TypeEnvironment
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...
33
34namespace SymTab {
35 namespace Mangler {
36 namespace {
37 /// Mangles names to a unique C identifier
38 struct Mangler : public WithShortCircuiting, public WithVisitorRef<Mangler>, public WithGuards {
39 Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams );
40 Mangler( const ResolvExpr::TypeEnvironment& env );
41 Mangler( const Mangler & ) = delete;
42
43 void previsit( BaseSyntaxNode * ) { visit_children = false; }
44
45 void postvisit( ObjectDecl * declaration );
46 void postvisit( FunctionDecl * declaration );
47 void postvisit( TypeDecl * declaration );
48
49 void postvisit( VoidType * voidType );
50 void postvisit( BasicType * basicType );
51 void postvisit( PointerType * pointerType );
52 void postvisit( ArrayType * arrayType );
53 void postvisit( ReferenceType * refType );
54 void postvisit( FunctionType * functionType );
55 void postvisit( StructInstType * aggregateUseType );
56 void postvisit( UnionInstType * aggregateUseType );
57 void postvisit( EnumInstType * aggregateUseType );
58 void postvisit( TypeInstType * aggregateUseType );
59 void postvisit( TraitInstType * inst );
60 void postvisit( TupleType * tupleType );
61 void postvisit( VarArgsType * varArgsType );
62 void postvisit( ZeroType * zeroType );
63 void postvisit( OneType * oneType );
64 void postvisit( QualifiedType * qualType );
65
66 std::string get_mangleName() { return mangleName.str(); }
67 private:
68 std::ostringstream mangleName; ///< Mangled name being constructed
69 typedef std::map< std::string, std::pair< std::string, int > > VarMapType;
70 VarMapType varNums; ///< Map of type variables to indices
71 int nextVarNum; ///< Next type variable index
72 const ResolvExpr::TypeEnvironment* env; ///< optional environment for substitutions
73 bool isTopLevel; ///< Is the Mangler at the top level
74 bool mangleOverridable; ///< Specially mangle overridable built-in methods
75 bool typeMode; ///< Produce a unique mangled name for a type
76 bool mangleGenericParams; ///< Include generic parameters in name mangling if true
77 bool inFunctionType = false; ///< Include type qualifiers if false.
78 bool inQualifiedType = false; ///< Add start/end delimiters around qualified type
79
80 public:
81 Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
82 int nextVarNum, const ResolvExpr::TypeEnvironment* env,
83 const VarMapType& varNums );
84
85 private:
86 void mangleDecl( DeclarationWithType *declaration );
87 void mangleRef( ReferenceToType *refType, std::string prefix );
88
89 void printQualifiers( Type *type );
90 }; // Mangler
91 } // namespace
92
93 std::string mangle( BaseSyntaxNode * decl, bool mangleOverridable, bool typeMode, bool mangleGenericParams ) {
94 PassVisitor<Mangler> mangler( mangleOverridable, typeMode, mangleGenericParams );
95 maybeAccept( decl, mangler );
96 return mangler.pass.get_mangleName();
97 }
98
99 std::string mangleType( Type * ty ) {
100 PassVisitor<Mangler> mangler( false, true, true );
101 maybeAccept( ty, mangler );
102 return mangler.pass.get_mangleName();
103 }
104
105 std::string mangleConcrete( Type * ty ) {
106 PassVisitor<Mangler> mangler( false, false, false );
107 maybeAccept( ty, mangler );
108 return mangler.pass.get_mangleName();
109 }
110
111 std::string mangleAssnKey( DeclarationWithType* decl,
112 const ResolvExpr::TypeEnvironment& env ) {
113 PassVisitor<Mangler> mangler( env );
114 maybeAccept( decl, mangler );
115 return mangler.pass.get_mangleName();
116 }
117
118 namespace {
119 Mangler::Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams )
120 : nextVarNum( 0 ), env(nullptr), isTopLevel( true ),
121 mangleOverridable( mangleOverridable ), typeMode( typeMode ),
122 mangleGenericParams( mangleGenericParams ) {}
123
124 Mangler::Mangler( const ResolvExpr::TypeEnvironment& env )
125 : nextVarNum( 0 ), env( &env ), isTopLevel( true ), mangleOverridable( false ),
126 typeMode( false ), mangleGenericParams( true ) {}
127
128 Mangler::Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
129 int nextVarNum, const ResolvExpr::TypeEnvironment* env,
130 const VarMapType& varNums )
131 : varNums( varNums ), nextVarNum( nextVarNum ), env( env ), isTopLevel( false ),
132 mangleOverridable( mangleOverridable ), typeMode( typeMode ),
133 mangleGenericParams( mangleGenericParams ) {}
134
135 void Mangler::mangleDecl( DeclarationWithType * declaration ) {
136 bool wasTopLevel = isTopLevel;
137 if ( isTopLevel ) {
138 varNums.clear();
139 nextVarNum = 0;
140 isTopLevel = false;
141 } // if
142 mangleName << Encoding::manglePrefix;
143 CodeGen::OperatorInfo opInfo;
144 if ( operatorLookup( declaration->get_name(), opInfo ) ) {
145 mangleName << opInfo.outputName.size() << opInfo.outputName;
146 } else {
147 mangleName << declaration->name.size() << declaration->name;
148 } // if
149 maybeAccept( declaration->get_type(), *visitor );
150 if ( mangleOverridable && LinkageSpec::isOverridable( declaration->get_linkage() ) ) {
151 // want to be able to override autogenerated and intrinsic routines,
152 // so they need a different name mangling
153 if ( declaration->get_linkage() == LinkageSpec::AutoGen ) {
154 mangleName << Encoding::autogen;
155 } else if ( declaration->get_linkage() == LinkageSpec::Intrinsic ) {
156 mangleName << Encoding::intrinsic;
157 } else {
158 // if we add another kind of overridable function, this has to change
159 assert( false && "unknown overrideable linkage" );
160 } // if
161 }
162 isTopLevel = wasTopLevel;
163 }
164
165 void Mangler::postvisit( ObjectDecl * declaration ) {
166 mangleDecl( declaration );
167 }
168
169 void Mangler::postvisit( FunctionDecl * declaration ) {
170 mangleDecl( declaration );
171 }
172
173 void Mangler::postvisit( VoidType * voidType ) {
174 printQualifiers( voidType );
175 mangleName << Encoding::void_t;
176 }
177
178 void Mangler::postvisit( BasicType * basicType ) {
179 printQualifiers( basicType );
180 assertf( basicType->get_kind() < BasicType::NUMBER_OF_BASIC_TYPES, "Unhandled basic type: %d", basicType->get_kind() );
181 mangleName << Encoding::basicTypes[ basicType->get_kind() ];
182 }
183
184 void Mangler::postvisit( PointerType * pointerType ) {
185 printQualifiers( pointerType );
186 // mangle void (*f)() and void f() to the same name to prevent overloading on functions and function pointers
187 if ( ! dynamic_cast<FunctionType *>( pointerType->base ) ) mangleName << Encoding::pointer;
188 maybeAccept( pointerType->base, *visitor );
189 }
190
191 void Mangler::postvisit( ArrayType * arrayType ) {
192 // TODO: encode dimension
193 printQualifiers( arrayType );
194 mangleName << Encoding::array << "0";
195 maybeAccept( arrayType->base, *visitor );
196 }
197
198 void Mangler::postvisit( ReferenceType * refType ) {
199 // don't print prefix (e.g. 'R') for reference types so that references and non-references do not overload.
200 // Further, do not print the qualifiers for a reference type (but do run printQualifers because of TypeDecls, etc.),
201 // by pretending every reference type is a function parameter.
202 GuardValue( inFunctionType );
203 inFunctionType = true;
204 printQualifiers( refType );
205 maybeAccept( refType->base, *visitor );
206 }
207
208 namespace {
209 inline std::list< Type* > getTypes( const std::list< DeclarationWithType* > decls ) {
210 std::list< Type* > ret;
211 std::transform( decls.begin(), decls.end(), std::back_inserter( ret ),
212 std::mem_fun( &DeclarationWithType::get_type ) );
213 return ret;
214 }
215 }
216
217 void Mangler::postvisit( FunctionType * functionType ) {
218 printQualifiers( functionType );
219 mangleName << Encoding::function;
220 // turn on inFunctionType so that printQualifiers does not print most qualifiers for function parameters,
221 // since qualifiers on outermost parameter type do not differentiate function types, e.g.,
222 // void (*)(const int) and void (*)(int) are the same type, but void (*)(const int *) and void (*)(int *) are different
223 GuardValue( inFunctionType );
224 inFunctionType = true;
225 std::list< Type* > returnTypes = getTypes( functionType->returnVals );
226 if (returnTypes.empty()) mangleName << Encoding::void_t;
227 else acceptAll( returnTypes, *visitor );
228 mangleName << "_";
229 std::list< Type* > paramTypes = getTypes( functionType->parameters );
230 acceptAll( paramTypes, *visitor );
231 mangleName << "_";
232 }
233
234 void Mangler::mangleRef( ReferenceToType * refType, std::string prefix ) {
235 printQualifiers( refType );
236
237 mangleName << prefix << refType->name.length() << refType->name;
238
239 if ( mangleGenericParams ) {
240 std::list< Expression* >& params = refType->parameters;
241 if ( ! params.empty() ) {
242 mangleName << "_";
243 for ( std::list< Expression* >::const_iterator param = params.begin(); param != params.end(); ++param ) {
244 TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
245 assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString(*param));
246 maybeAccept( paramType->type, *visitor );
247 }
248 mangleName << "_";
249 }
250 }
251 }
252
253 void Mangler::postvisit( StructInstType * aggregateUseType ) {
254 mangleRef( aggregateUseType, Encoding::struct_t );
255 }
256
257 void Mangler::postvisit( UnionInstType * aggregateUseType ) {
258 mangleRef( aggregateUseType, Encoding::union_t );
259 }
260
261 void Mangler::postvisit( EnumInstType * aggregateUseType ) {
262 mangleRef( aggregateUseType, Encoding::enum_t );
263 }
264
265 void Mangler::postvisit( TypeInstType * typeInst ) {
266 VarMapType::iterator varNum = varNums.find( typeInst->get_name() );
267 if ( varNum == varNums.end() ) {
268 mangleRef( typeInst, Encoding::type );
269 } else {
270 printQualifiers( typeInst );
271 // Note: Can't use name here, since type variable names do not actually disambiguate a function, e.g.
272 // forall(dtype T) void f(T);
273 // forall(dtype S) void f(S);
274 // are equivalent and should mangle the same way. This is accomplished by numbering the type variables when they
275 // are first found and prefixing with the appropriate encoding for the type class.
276 assertf( varNum->second.second < TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", varNum->second.second );
277 mangleName << Encoding::typeVariables[varNum->second.second] << varNum->second.first;
278 } // if
279 }
280
281 void Mangler::postvisit( TraitInstType * inst ) {
282 printQualifiers( inst );
283 mangleName << inst->name.size() << inst->name;
284 }
285
286 void Mangler::postvisit( TupleType * tupleType ) {
287 printQualifiers( tupleType );
288 mangleName << Encoding::tuple << tupleType->types.size();
289 acceptAll( tupleType->types, *visitor );
290 }
291
292 void Mangler::postvisit( VarArgsType * varArgsType ) {
293 printQualifiers( varArgsType );
294 static const std::string vargs = "__builtin_va_list";
295 mangleName << Encoding::type << vargs.size() << vargs;
296 }
297
298 void Mangler::postvisit( ZeroType * ) {
299 mangleName << Encoding::zero;
300 }
301
302 void Mangler::postvisit( OneType * ) {
303 mangleName << Encoding::one;
304 }
305
306 void Mangler::postvisit( QualifiedType * qualType ) {
307 bool inqual = inQualifiedType;
308 if (! inqual ) {
309 // N marks the start of a qualified type
310 inQualifiedType = true;
311 mangleName << Encoding::qualifiedTypeStart;
312 }
313 maybeAccept( qualType->parent, *visitor );
314 maybeAccept( qualType->child, *visitor );
315 if ( ! inqual ) {
316 // E marks the end of a qualified type
317 inQualifiedType = false;
318 mangleName << Encoding::qualifiedTypeEnd;
319 }
320 }
321
322 void Mangler::postvisit( TypeDecl * decl ) {
323 // TODO: is there any case where mangling a TypeDecl makes sense? If so, this code needs to be
324 // fixed to ensure that two TypeDecls mangle to the same name when they are the same type and vice versa.
325 // Note: The current scheme may already work correctly for this case, I have not thought about this deeply
326 // and the case has not yet come up in practice. Alternatively, if not then this code can be removed
327 // aside from the assert false.
328 assertf(false, "Mangler should not visit typedecl: %s", toCString(decl));
329 assertf( decl->get_kind() < TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->get_kind() );
330 mangleName << Encoding::typeVariables[ decl->get_kind() ] << ( decl->name.length() ) << decl->name;
331 }
332
333 __attribute__((unused)) void printVarMap( const std::map< std::string, std::pair< int, int > > &varMap, std::ostream &os ) {
334 for ( std::map< std::string, std::pair< int, int > >::const_iterator i = varMap.begin(); i != varMap.end(); ++i ) {
335 os << i->first << "(" << i->second.first << "/" << i->second.second << ")" << std::endl;
336 } // for
337 }
338
339 void Mangler::printQualifiers( Type * type ) {
340 // skip if not including qualifiers
341 if ( typeMode ) return;
342 if ( ! type->get_forall().empty() ) {
343 std::list< std::string > assertionNames;
344 int dcount = 0, fcount = 0, vcount = 0, acount = 0;
345 mangleName << Encoding::forall;
346 for ( Type::ForallList::iterator i = type->forall.begin(); i != type->forall.end(); ++i ) {
347 switch ( (*i)->get_kind() ) {
348 case TypeDecl::Dtype:
349 dcount++;
350 break;
351 case TypeDecl::Ftype:
352 fcount++;
353 break;
354 case TypeDecl::Ttype:
355 vcount++;
356 break;
357 default:
358 assert( false );
359 } // switch
360 std::string varName;
361 // replace type with substitution name if environment is available and bound
362 if ( env ) {
363 const ResolvExpr::EqvClass* varClass = env->lookup( (*i)->name );
364 if ( varClass && varClass->type ) {
365 PassVisitor<Mangler> sub_mangler(
366 mangleOverridable, typeMode, mangleGenericParams, nextVarNum,
367 env, varNums );
368 varClass->type->accept( sub_mangler );
369 varName = std::string{"%"} + sub_mangler.pass.get_mangleName();
370 }
371 }
372 // otherwise just give type numeric name
373 if ( varName.empty() ) {
374 varName = std::to_string( nextVarNum++ );
375 }
376 varNums[ (*i)->name ] = std::make_pair( varName, (int)(*i)->get_kind() );
377 for ( std::list< DeclarationWithType* >::iterator assert = (*i)->assertions.begin(); assert != (*i)->assertions.end(); ++assert ) {
378 PassVisitor<Mangler> sub_mangler(
379 mangleOverridable, typeMode, mangleGenericParams, nextVarNum, env,
380 varNums );
381 (*assert)->accept( sub_mangler );
382 assertionNames.push_back( sub_mangler.pass.get_mangleName() );
383 acount++;
384 } // for
385 } // for
386 mangleName << dcount << "_" << fcount << "_" << vcount << "_" << acount << "_";
387 std::copy( assertionNames.begin(), assertionNames.end(), std::ostream_iterator< std::string >( mangleName, "" ) );
388 mangleName << "_";
389 } // if
390 if ( ! inFunctionType ) {
391 // these qualifiers do not distinguish the outermost type of a function parameter
392 if ( type->get_const() ) {
393 mangleName << Encoding::qualifiers.at(Type::Const);
394 } // if
395 if ( type->get_volatile() ) {
396 mangleName << Encoding::qualifiers.at(Type::Volatile);
397 } // if
398 // Removed due to restrict not affecting function compatibility in GCC
399 // if ( type->get_isRestrict() ) {
400 // mangleName << "E";
401 // } // if
402 if ( type->get_atomic() ) {
403 mangleName << Encoding::qualifiers.at(Type::Atomic);
404 } // if
405 }
406 if ( type->get_mutex() ) {
407 mangleName << Encoding::qualifiers.at(Type::Mutex);
408 } // if
409 if ( type->get_lvalue() ) {
410 // mangle based on whether the type is lvalue, so that the resolver can differentiate lvalues and rvalues
411 mangleName << Encoding::qualifiers.at(Type::Lvalue);
412 }
413
414 if ( inFunctionType ) {
415 // turn off inFunctionType so that types can be differentiated for nested qualifiers
416 GuardValue( inFunctionType );
417 inFunctionType = false;
418 }
419 }
420 } // namespace
421 } // namespace Mangler
422} // namespace SymTab
423
424// Local Variables: //
425// tab-width: 4 //
426// mode: c++ //
427// compile-command: "make install" //
428// End: //
Note: See TracBrowser for help on using the repository browser.