Changeset b0845f9 for src/SymTab/Mangler.cc
- Timestamp:
- Nov 17, 2023, 10:40:21 AM (6 months ago)
- Branches:
- master
- Children:
- 0f6d2884
- Parents:
- e580aa5
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/SymTab/Mangler.cc
re580aa5 rb0845f9 28 28 29 29 namespace 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 30 31 namespace { 32 33 /// Mangles names to a unique C identifier. 34 struct 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; } 63 private: 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 75 private: 76 Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 77 int nextVarNum, const VarMapType& varNums ); 78 friend class ast::Pass<Mangler>; 79 80 private: 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 87 Mangler::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 93 Mangler::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 99 void 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 128 void Mangler::postvisit( const ast::ObjectDecl * decl ) { 129 mangleDecl( decl ); 130 } 131 132 void Mangler::postvisit( const ast::FunctionDecl * decl ) { 133 mangleDecl( decl ); 134 } 135 136 void Mangler::postvisit( const ast::VoidType * voidType ) { 137 printQualifiers( voidType ); 138 mangleName += Encoding::void_t; 139 } 140 141 void 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 147 void 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 154 void 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 161 void 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 170 void 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 184 void 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 201 void Mangler::postvisit( const ast::StructInstType * aggregateUseType ) { 202 mangleRef( aggregateUseType, Encoding::struct_t ); 203 } 204 205 void Mangler::postvisit( const ast::UnionInstType * aggregateUseType ) { 206 mangleRef( aggregateUseType, Encoding::union_t ); 207 } 208 209 void Mangler::postvisit( const ast::EnumInstType * aggregateUseType ) { 210 mangleRef( aggregateUseType, Encoding::enum_t ); 211 } 212 213 void 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 229 void Mangler::postvisit( const ast::TraitInstType * inst ) { 230 printQualifiers( inst ); 231 mangleName += std::to_string( inst->name.size() ) + inst->name; 232 } 233 234 void 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 240 void 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 246 void Mangler::postvisit( const ast::ZeroType * ) { 247 mangleName += Encoding::zero; 248 } 249 250 void Mangler::postvisit( const ast::OneType * ) { 251 mangleName += Encoding::one; 252 } 253 254 void 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 270 void 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 288 void 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() ); 129 309 } 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 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 345 std::string mangle( const ast::Node * decl, Mangle::Mode mode ) { 346 return ast::Pass<Mangler>::read( decl, mode ); 347 } 348 355 349 } // namespace Mangle 356 350
Note: See TracChangeset
for help on using the changeset viewer.