source: src/SymTab/Mangler.cc@ 96df1329

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 96df1329 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
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
[201aeb9]11// Last Modified By : Peter A. Buhr
12// Last Modified On : Mon Sep 25 15:49:26 2017
13// Update Count : 23
[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
24#include "CodeGen/OperatorTable.h" // for OperatorInfo, operatorLookup
[d7d9a60]25#include "Common/PassVisitor.h"
[ff5caaf]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...
[51b73452]33
34namespace SymTab {
[d7d9a60]35 namespace Mangler {
36 namespace {
37 /// Mangles names to a unique C identifier
[c0453ca3]38 struct Mangler : public WithShortCircuiting, public WithVisitorRef<Mangler>, public WithGuards {
[d7d9a60]39 Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams );
[ff5caaf]40 Mangler( const ResolvExpr::TypeEnvironment& env );
[b8a52f5]41 Mangler( const Mangler & ) = delete;
[d7d9a60]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 );
[f465f0e]59 void postvisit( TraitInstType * inst );
[d7d9a60]60 void postvisit( TupleType * tupleType );
61 void postvisit( VarArgsType * varArgsType );
62 void postvisit( ZeroType * zeroType );
63 void postvisit( OneType * oneType );
[e73becf]64 void postvisit( QualifiedType * qualType );
[d7d9a60]65
66 std::string get_mangleName() { return mangleName.str(); }
67 private:
68 std::ostringstream mangleName; ///< Mangled name being constructed
[ff5caaf]69 typedef std::map< std::string, std::pair< std::string, int > > VarMapType;
[d7d9a60]70 VarMapType varNums; ///< Map of type variables to indices
71 int nextVarNum; ///< Next type variable index
[e1f7eef]72 const ResolvExpr::TypeEnvironment* env; ///< optional environment for substitutions
[d7d9a60]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
[c0453ca3]77 bool inFunctionType = false; ///< Include type qualifiers if false.
[642bc83]78 bool inQualifiedType = false; ///< Add start/end delimiters around qualified type
[d7d9a60]79
[e1f7eef]80 public:
[ff5caaf]81 Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
82 int nextVarNum, const ResolvExpr::TypeEnvironment* env,
83 const VarMapType& varNums );
84
[e1f7eef]85 private:
[d7d9a60]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();
[4aa0858]97 }
[d7d9a60]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();
[0dd3a2f]109 }
[d7d9a60]110
[ff5caaf]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
[d7d9a60]118 namespace {
119 Mangler::Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams )
[ff5caaf]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 )
[e1f7eef]131 : varNums( varNums ), nextVarNum( nextVarNum ), env( env ), isTopLevel( false ),
[ff5caaf]132 mangleOverridable( mangleOverridable ), typeMode( typeMode ),
133 mangleGenericParams( mangleGenericParams ) {}
[d7d9a60]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
[642bc83]142 mangleName << Encoding::manglePrefix;
[d7d9a60]143 CodeGen::OperatorInfo opInfo;
144 if ( operatorLookup( declaration->get_name(), opInfo ) ) {
[642bc83]145 mangleName << opInfo.outputName.size() << opInfo.outputName;
[d7d9a60]146 } else {
[642bc83]147 mangleName << declaration->name.size() << declaration->name;
[d7d9a60]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 ) {
[642bc83]154 mangleName << Encoding::autogen;
[d7d9a60]155 } else if ( declaration->get_linkage() == LinkageSpec::Intrinsic ) {
[642bc83]156 mangleName << Encoding::intrinsic;
[d7d9a60]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 );
[7804e2a]175 mangleName << Encoding::void_t;
[d7d9a60]176 }
177
178 void Mangler::postvisit( BasicType * basicType ) {
179 printQualifiers( basicType );
[0e73845]180 assertf( basicType->get_kind() < BasicType::NUMBER_OF_BASIC_TYPES, "Unhandled basic type: %d", basicType->get_kind() );
[642bc83]181 mangleName << Encoding::basicTypes[ basicType->get_kind() ];
[d7d9a60]182 }
183
184 void Mangler::postvisit( PointerType * pointerType ) {
185 printQualifiers( pointerType );
[3f024c9]186 // mangle void (*f)() and void f() to the same name to prevent overloading on functions and function pointers
[642bc83]187 if ( ! dynamic_cast<FunctionType *>( pointerType->base ) ) mangleName << Encoding::pointer;
[1da22500]188 maybeAccept( pointerType->base, *visitor );
[d7d9a60]189 }
190
191 void Mangler::postvisit( ArrayType * arrayType ) {
192 // TODO: encode dimension
193 printQualifiers( arrayType );
[642bc83]194 mangleName << Encoding::array << "0";
[1da22500]195 maybeAccept( arrayType->base, *visitor );
[d7d9a60]196 }
197
198 void Mangler::postvisit( ReferenceType * refType ) {
[c0453ca3]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;
[d7d9a60]204 printQualifiers( refType );
[1da22500]205 maybeAccept( refType->base, *visitor );
[d7d9a60]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 );
[642bc83]219 mangleName << Encoding::function;
[c0453ca3]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;
[96812c0]225 std::list< Type* > returnTypes = getTypes( functionType->returnVals );
[7804e2a]226 if (returnTypes.empty()) mangleName << Encoding::void_t;
[d1e0979]227 else acceptAll( returnTypes, *visitor );
[d7d9a60]228 mangleName << "_";
[96812c0]229 std::list< Type* > paramTypes = getTypes( functionType->parameters );
[d7d9a60]230 acceptAll( paramTypes, *visitor );
[e35f30a]231 mangleName << "_";
[d7d9a60]232 }
233
234 void Mangler::mangleRef( ReferenceToType * refType, std::string prefix ) {
235 printQualifiers( refType );
236
[642bc83]237 mangleName << prefix << refType->name.length() << refType->name;
[d7d9a60]238
239 if ( mangleGenericParams ) {
[96812c0]240 std::list< Expression* >& params = refType->parameters;
[d7d9a60]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 );
[96812c0]245 assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString(*param));
246 maybeAccept( paramType->type, *visitor );
[d7d9a60]247 }
248 mangleName << "_";
249 }
[e35f30a]250 }
[d7d9a60]251 }
252
253 void Mangler::postvisit( StructInstType * aggregateUseType ) {
[7804e2a]254 mangleRef( aggregateUseType, Encoding::struct_t );
[d7d9a60]255 }
256
257 void Mangler::postvisit( UnionInstType * aggregateUseType ) {
[7804e2a]258 mangleRef( aggregateUseType, Encoding::union_t );
[d7d9a60]259 }
260
261 void Mangler::postvisit( EnumInstType * aggregateUseType ) {
[7804e2a]262 mangleRef( aggregateUseType, Encoding::enum_t );
[d7d9a60]263 }
264
265 void Mangler::postvisit( TypeInstType * typeInst ) {
266 VarMapType::iterator varNum = varNums.find( typeInst->get_name() );
267 if ( varNum == varNums.end() ) {
[d8cb7df]268 mangleRef( typeInst, Encoding::type );
[d7d9a60]269 } else {
270 printQualifiers( typeInst );
[0e761e40]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.
[0e73845]276 assertf( varNum->second.second < TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", varNum->second.second );
[0e761e40]277 mangleName << Encoding::typeVariables[varNum->second.second] << varNum->second.first;
[d7d9a60]278 } // if
279 }
280
[f465f0e]281 void Mangler::postvisit( TraitInstType * inst ) {
282 printQualifiers( inst );
[642bc83]283 mangleName << inst->name.size() << inst->name;
[f465f0e]284 }
285
[d7d9a60]286 void Mangler::postvisit( TupleType * tupleType ) {
287 printQualifiers( tupleType );
[642bc83]288 mangleName << Encoding::tuple << tupleType->types.size();
[d7d9a60]289 acceptAll( tupleType->types, *visitor );
[8360977]290 }
[d7d9a60]291
292 void Mangler::postvisit( VarArgsType * varArgsType ) {
293 printQualifiers( varArgsType );
[642bc83]294 static const std::string vargs = "__builtin_va_list";
[d8cb7df]295 mangleName << Encoding::type << vargs.size() << vargs;
[d7d9a60]296 }
297
298 void Mangler::postvisit( ZeroType * ) {
[642bc83]299 mangleName << Encoding::zero;
[d7d9a60]300 }
301
302 void Mangler::postvisit( OneType * ) {
[642bc83]303 mangleName << Encoding::one;
[d7d9a60]304 }
305
[e73becf]306 void Mangler::postvisit( QualifiedType * qualType ) {
[642bc83]307 bool inqual = inQualifiedType;
308 if (! inqual ) {
309 // N marks the start of a qualified type
310 inQualifiedType = true;
311 mangleName << Encoding::qualifiedTypeStart;
312 }
[e73becf]313 maybeAccept( qualType->parent, *visitor );
314 maybeAccept( qualType->child, *visitor );
[642bc83]315 if ( ! inqual ) {
316 // E marks the end of a qualified type
317 inQualifiedType = false;
318 mangleName << Encoding::qualifiedTypeEnd;
319 }
[e73becf]320 }
321
[d7d9a60]322 void Mangler::postvisit( TypeDecl * decl ) {
[0e761e40]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));
[0e73845]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;
[d7d9a60]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;
[0dd3a2f]336 } // for
[d7d9a60]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;
[0e73845]344 int dcount = 0, fcount = 0, vcount = 0, acount = 0;
345 mangleName << Encoding::forall;
[d7d9a60]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
[ff5caaf]360 std::string varName;
361 // replace type with substitution name if environment is available and bound
362 if ( env ) {
[e1f7eef]363 const ResolvExpr::EqvClass* varClass = env->lookup( (*i)->name );
[ff5caaf]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() );
[d7d9a60]377 for ( std::list< DeclarationWithType* >::iterator assert = (*i)->assertions.begin(); assert != (*i)->assertions.end(); ++assert ) {
[ff5caaf]378 PassVisitor<Mangler> sub_mangler(
379 mangleOverridable, typeMode, mangleGenericParams, nextVarNum, env,
380 varNums );
[d7d9a60]381 (*assert)->accept( sub_mangler );
[ff5caaf]382 assertionNames.push_back( sub_mangler.pass.get_mangleName() );
[0e73845]383 acount++;
[d7d9a60]384 } // for
385 } // for
[0e73845]386 mangleName << dcount << "_" << fcount << "_" << vcount << "_" << acount << "_";
[d7d9a60]387 std::copy( assertionNames.begin(), assertionNames.end(), std::ostream_iterator< std::string >( mangleName, "" ) );
388 mangleName << "_";
389 } // if
[c0453ca3]390 if ( ! inFunctionType ) {
391 // these qualifiers do not distinguish the outermost type of a function parameter
392 if ( type->get_const() ) {
[642bc83]393 mangleName << Encoding::qualifiers.at(Type::Const);
[c0453ca3]394 } // if
395 if ( type->get_volatile() ) {
[642bc83]396 mangleName << Encoding::qualifiers.at(Type::Volatile);
[c0453ca3]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() ) {
[642bc83]403 mangleName << Encoding::qualifiers.at(Type::Atomic);
[c0453ca3]404 } // if
405 }
[d7d9a60]406 if ( type->get_mutex() ) {
[642bc83]407 mangleName << Encoding::qualifiers.at(Type::Mutex);
[d7d9a60]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
[642bc83]411 mangleName << Encoding::qualifiers.at(Type::Lvalue);
[d7d9a60]412 }
[c0453ca3]413
414 if ( inFunctionType ) {
415 // turn off inFunctionType so that types can be differentiated for nested qualifiers
416 GuardValue( inFunctionType );
417 inFunctionType = false;
418 }
[d7d9a60]419 }
420 } // namespace
421 } // namespace Mangler
[0dd3a2f]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.