source: src/SymTab/Mangler.cc @ 8984003

Last change on this file since 8984003 was 8984003, checked in by Andrew Beach <ajbeach@…>, 7 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.