source: src/SymTab/Mangler.cc @ 4c0b674

Last change on this file since 4c0b674 was 0522ebe, checked in by JiadaL <j82liang@…>, 4 months ago

Add EnumPosType? to type system

  • Property mode set to 100644
File size: 13.8 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        void postvisit( const ast::EnumPosType * posType );
62
63        /// The result is the current constructed mangled name.
64        std::string result() const { return mangleName; }
65private:
66        std::string mangleName;         ///< Mangled name being constructed
67        typedef std::map< std::string, std::pair< int, int > > VarMapType;
68        VarMapType varNums;             ///< Map of type variables to indices
69        int nextVarNum;                 ///< Next type variable index
70        bool isTopLevel;                ///< Is the Mangler at the top level
71        bool mangleOverridable;         ///< Specially mangle overridable built-in methods
72        bool typeMode;                  ///< Produce a unique mangled name for a type
73        bool mangleGenericParams;       ///< Include generic parameters in name mangling if true
74        bool inFunctionType = false;    ///< Include type qualifiers if false.
75        bool inQualifiedType = false;   ///< Add start/end delimiters around qualified type
76
77private:
78        Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
79                int nextVarNum, const VarMapType& varNums );
80        friend class ast::Pass<Mangler>;
81
82private:
83        void mangleDecl( const ast::DeclWithType *declaration );
84        void mangleRef( const ast::BaseInstType *refType, const std::string & prefix );
85
86        void printQualifiers( const ast::Type *type );
87}; // Mangler
88
89Mangler::Mangler( Mangle::Mode mode )
90        : nextVarNum( 0 ), isTopLevel( true ),
91        mangleOverridable  ( ! mode.no_overrideable   ),
92        typeMode           (   mode.type              ),
93        mangleGenericParams( ! mode.no_generic_params ) {}
94
95Mangler::Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
96        int nextVarNum, const VarMapType& varNums )
97        : varNums( varNums ), nextVarNum( nextVarNum ), isTopLevel( false ),
98        mangleOverridable( mangleOverridable ), typeMode( typeMode ),
99        mangleGenericParams( mangleGenericParams ) {}
100
101void Mangler::mangleDecl( const ast::DeclWithType * decl ) {
102        bool wasTopLevel = isTopLevel;
103        if ( isTopLevel ) {
104                varNums.clear();
105                nextVarNum = 0;
106                isTopLevel = false;
107        }
108        mangleName += Encoding::manglePrefix;
109        if ( auto opInfo = CodeGen::operatorLookup( decl->name ) ) {
110                mangleName += std::to_string( opInfo->outputName.size() ) + opInfo->outputName;
111        } else {
112                mangleName += std::to_string( decl->name.size() ) + decl->name;
113        }
114        decl->get_type()->accept( *visitor );
115        if ( mangleOverridable && decl->linkage.is_overrideable ) {
116                // want to be able to override autogenerated and intrinsic routines,
117                // so they need a different name mangling
118                if ( decl->linkage == ast::Linkage::AutoGen ) {
119                        mangleName += Encoding::autogen;
120                } else if ( decl->linkage == ast::Linkage::Intrinsic ) {
121                        mangleName += Encoding::intrinsic;
122                } else {
123                        // if we add another kind of overridable function, this has to change
124                        assert( false && "unknown overrideable linkage" );
125                }
126        }
127        isTopLevel = wasTopLevel;
128}
129
130void Mangler::postvisit( const ast::ObjectDecl * decl ) {
131        mangleDecl( decl );
132}
133
134void Mangler::postvisit( const ast::FunctionDecl * decl ) {
135        mangleDecl( decl );
136}
137
138void Mangler::postvisit( const ast::VoidType * voidType ) {
139        printQualifiers( voidType );
140        mangleName += Encoding::void_t;
141}
142
143void Mangler::postvisit( const ast::BasicType * basicType ) {
144        printQualifiers( basicType );
145        assertf( basicType->kind < ast::BasicType::NUMBER_OF_BASIC_TYPES, "Unhandled basic type: %d", basicType->kind );
146        mangleName += Encoding::basicTypes[ basicType->kind ];
147}
148
149void Mangler::postvisit( const ast::PointerType * pointerType ) {
150        printQualifiers( pointerType );
151        // Mangle void (*f)() and void f() to the same name to prevent overloading on functions and function pointers.
152        if ( !pointerType->base.as<ast::FunctionType>() ) mangleName += Encoding::pointer;
153        maybe_accept( pointerType->base.get(), *visitor );
154}
155
156void Mangler::postvisit( const ast::ArrayType * arrayType ) {
157        // TODO: encode dimension
158        printQualifiers( arrayType );
159        mangleName += Encoding::array + "0";
160        arrayType->base->accept( *visitor );
161}
162
163void Mangler::postvisit( const ast::ReferenceType * refType ) {
164        // Don't print prefix (e.g. 'R') for reference types so that references and non-references do not overload.
165        // Further, do not print the qualifiers for a reference type (but do run printQualifers because of TypeDecls, etc.),
166        // by pretending every reference type is a function parameter.
167        GuardValue( inFunctionType ) = true;
168        printQualifiers( refType );
169        refType->base->accept( *visitor );
170}
171
172void Mangler::postvisit( const ast::FunctionType * functionType ) {
173        printQualifiers( functionType );
174        mangleName += Encoding::function;
175        // Turn on inFunctionType so that printQualifiers does not print most qualifiers for function parameters,
176        // since qualifiers on outermost parameter type do not differentiate function types, e.g.,
177        // void (*)(const int) and void (*)(int) are the same type, but void (*)(const int *) and void (*)(int *) are different.
178        GuardValue( inFunctionType ) = true;
179        if (functionType->returns.empty()) mangleName += Encoding::void_t;
180        else accept_each( functionType->returns, *visitor );
181        mangleName += "_";
182        accept_each( functionType->params, *visitor );
183        mangleName += "_";
184}
185
186void Mangler::mangleRef(
187                const ast::BaseInstType * refType, const std::string & prefix ) {
188        printQualifiers( refType );
189
190        mangleName += prefix + std::to_string( refType->name.length() ) + refType->name;
191
192        if ( mangleGenericParams && ! refType->params.empty() ) {
193                mangleName += "_";
194                for ( const ast::Expr * param : refType->params ) {
195                        auto paramType = dynamic_cast< const ast::TypeExpr * >( param );
196                        assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString(param));
197                        paramType->type->accept( *visitor );
198                }
199                mangleName += "_";
200        }
201}
202
203void Mangler::postvisit( const ast::StructInstType * aggregateUseType ) {
204        mangleRef( aggregateUseType, Encoding::struct_t );
205}
206
207void Mangler::postvisit( const ast::UnionInstType * aggregateUseType ) {
208        mangleRef( aggregateUseType, Encoding::union_t );
209}
210
211void Mangler::postvisit( const ast::EnumInstType * aggregateUseType ) {
212        mangleRef( aggregateUseType, Encoding::enum_t );
213}
214
215void Mangler::postvisit( const ast::TypeInstType * typeInst ) {
216        VarMapType::iterator varNum = varNums.find( typeInst->name );
217        if ( varNum == varNums.end() ) {
218                mangleRef( typeInst, Encoding::type );
219        } else {
220                printQualifiers( typeInst );
221                // Note: Can't use name here, since type variable names do not actually disambiguate a function, e.g.
222                //   forall(dtype T) void f(T);
223                //   forall(dtype S) void f(S);
224                // are equivalent and should mangle the same way. This is accomplished by numbering the type variables when they
225                // are first found and prefixing with the appropriate encoding for the type class.
226                assertf( varNum->second.second < ast::TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", varNum->second.second );
227                mangleName += Encoding::typeVariables[varNum->second.second] + std::to_string( varNum->second.first );
228        }
229}
230
231void Mangler::postvisit( const ast::TraitInstType * inst ) {
232        printQualifiers( inst );
233        mangleName += std::to_string( inst->name.size() ) + inst->name;
234}
235
236void Mangler::postvisit( const ast::TupleType * tupleType ) {
237        printQualifiers( tupleType );
238        mangleName += Encoding::tuple + std::to_string( tupleType->types.size() );
239        accept_each( tupleType->types, *visitor );
240}
241
242void Mangler::postvisit( const ast::VarArgsType * varArgsType ) {
243        printQualifiers( varArgsType );
244        static const std::string vargs = "__builtin_va_list";
245        mangleName += Encoding::type + std::to_string( vargs.size() ) + vargs;
246}
247
248void Mangler::postvisit( const ast::ZeroType * ) {
249        mangleName += Encoding::zero;
250}
251
252void Mangler::postvisit( const ast::OneType * ) {
253        mangleName += Encoding::one;
254}
255
256void Mangler::postvisit( const ast::QualifiedType * qualType ) {
257        bool inqual = inQualifiedType;
258        if ( !inqual ) {
259                // N marks the start of a qualified type.
260                inQualifiedType = true;
261                mangleName += Encoding::qualifiedTypeStart;
262        }
263        qualType->parent->accept( *visitor );
264        qualType->child->accept( *visitor );
265        if ( !inqual ) {
266                // E marks the end of a qualified type.
267                inQualifiedType = false;
268                mangleName += Encoding::qualifiedTypeEnd;
269        }
270}
271
272void Mangler::postvisit( const ast::TypeDecl * decl ) {
273        // TODO: is there any case where mangling a TypeDecl makes sense? If so, this code needs to be
274        // fixed to ensure that two TypeDecls mangle to the same name when they are the same type and vice versa.
275        // Note: The current scheme may already work correctly for this case, I have not thought about this deeply
276        // and the case has not yet come up in practice. Alternatively, if not then this code can be removed
277        // aside from the assert false.
278        assertf(false, "Mangler should not visit typedecl: %s", toCString(decl));
279        assertf( decl->kind < ast::TypeDecl::Kind::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->kind );
280        mangleName += Encoding::typeVariables[ decl->kind ] + std::to_string( decl->name.length() ) + decl->name;
281}
282
283void Mangler::postvisit( const ast::EnumPosType * pos ) {
284        postvisit( pos->instance );
285        mangleName += "_pos";
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        }
293}
294
295void 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", Encoding::typeVariables[decl->kind].c_str() );
316                        }
317                        varNums[ decl->name ] = std::make_pair( nextVarNum, (int)decl->kind );
318                }
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                }
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        }
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                }
334                if ( type->is_volatile() ) {
335                        mangleName += Encoding::qualifiers.at( ast::CV::Volatile );
336                }
337                if ( type->is_atomic() ) {
338                        mangleName += Encoding::qualifiers.at( ast::CV::Atomic );
339                }
340        }
341        if ( type->is_mutex() ) {
342                mangleName += Encoding::qualifiers.at( ast::CV::Mutex );
343        }
344        if ( inFunctionType ) {
345                // Turn off inFunctionType so that types can be differentiated for nested qualifiers.
346                GuardValue( inFunctionType ) = false;
347        }
348}
349
350} // namespace
351
352std::string mangle( const ast::Node * decl, Mangle::Mode mode ) {
353        return ast::Pass<Mangler>::read( decl, mode );
354}
355
356} // namespace Mangle
357
358// Local Variables: //
359// tab-width: 4 //
360// mode: c++ //
361// compile-command: "make install" //
362// End: //
Note: See TracBrowser for help on using the repository browser.