Changeset b0845f9 for src/SymTab
- Timestamp:
- Nov 17, 2023, 10:40:21 AM (13 months ago)
- Branches:
- master
- Children:
- 0f6d2884
- Parents:
- e580aa5
- Location:
- src/SymTab
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
src/SymTab/FixFunction.cc
re580aa5 rb0845f9 26 26 27 27 namespace { 28 struct FixFunction final : public ast::WithShortCircuiting {29 bool isVoid = false;30 28 31 void previsit( const ast::FunctionDecl * ) { visit_children = false; } 29 struct FixFunction final : public ast::WithShortCircuiting { 30 bool isVoid = false; 32 31 33 const ast::DeclWithType * postvisit( const ast::FunctionDecl * func ) { 34 // Cannot handle cases with asserions. 35 assert( func->assertions.empty() ); 36 return new ast::ObjectDecl{ 37 func->location, func->name, new ast::PointerType( func->type ), nullptr, 38 func->storage, func->linkage, nullptr, copy( func->attributes ) }; 39 } 32 void previsit( const ast::FunctionDecl * ) { visit_children = false; } 40 33 41 void previsit( const ast::ArrayType * ) { visit_children = false; } 34 const ast::DeclWithType * postvisit( const ast::FunctionDecl * func ) { 35 // Cannot handle cases with asserions. 36 assert( func->assertions.empty() ); 37 return new ast::ObjectDecl{ 38 func->location, func->name, new ast::PointerType( func->type ), nullptr, 39 func->storage, func->linkage, nullptr, copy( func->attributes ) }; 40 } 42 41 43 const ast::Type * postvisit( const ast::ArrayType * array ) { 44 return new ast::PointerType{ 45 array->base, array->dimension, array->isVarLen, array->isStatic, 46 array->qualifiers }; 47 } 42 void previsit( const ast::ArrayType * ) { visit_children = false; } 48 43 49 void previsit( const ast::FunctionType * ) { visit_children = false; } 44 const ast::Type * postvisit( const ast::ArrayType * array ) { 45 return new ast::PointerType{ 46 array->base, array->dimension, array->isVarLen, array->isStatic, 47 array->qualifiers }; 48 } 50 49 51 const ast::Type * postvisit( const ast::FunctionType * type ) { 52 return new ast::PointerType( type ); 53 } 50 void previsit( const ast::FunctionType * ) { visit_children = false; } 54 51 55 void previsit( const ast::VoidType * ) { isVoid = true; } 52 const ast::Type * postvisit( const ast::FunctionType * type ) { 53 return new ast::PointerType( type ); 54 } 56 55 57 void previsit( const ast::BasicType * ) { visit_children = false; } 58 void previsit( const ast::PointerType * ) { visit_children = false; } 59 void previsit( const ast::StructInstType * ) { visit_children = false; } 60 void previsit( const ast::UnionInstType * ) { visit_children = false; } 61 void previsit( const ast::EnumInstType * ) { visit_children = false; } 62 void previsit( const ast::TraitInstType * ) { visit_children = false; } 63 void previsit( const ast::TypeInstType * ) { visit_children = false; } 64 void previsit( const ast::TupleType * ) { visit_children = false; } 65 void previsit( const ast::VarArgsType * ) { visit_children = false; } 66 void previsit( const ast::ZeroType * ) { visit_children = false; } 67 void previsit( const ast::OneType * ) { visit_children = false; } 68 }; 56 void previsit( const ast::VoidType * ) { isVoid = true; } 57 58 void previsit( const ast::BasicType * ) { visit_children = false; } 59 void previsit( const ast::PointerType * ) { visit_children = false; } 60 void previsit( const ast::StructInstType * ) { visit_children = false; } 61 void previsit( const ast::UnionInstType * ) { visit_children = false; } 62 void previsit( const ast::EnumInstType * ) { visit_children = false; } 63 void previsit( const ast::TraitInstType * ) { visit_children = false; } 64 void previsit( const ast::TypeInstType * ) { visit_children = false; } 65 void previsit( const ast::TupleType * ) { visit_children = false; } 66 void previsit( const ast::VarArgsType * ) { visit_children = false; } 67 void previsit( const ast::ZeroType * ) { visit_children = false; } 68 void previsit( const ast::OneType * ) { visit_children = false; } 69 }; 70 69 71 } // anonymous namespace 70 72 -
src/SymTab/FixFunction.h
re580aa5 rb0845f9 22 22 23 23 namespace SymTab { 24 /// Returns declaration with function and array types replaced by equivalent pointer types. 25 /// Sets isVoid to true if type is void 26 const ast::DeclWithType * fixFunction( const ast::DeclWithType * dwt, bool & isVoid ); 27 const ast::Type * fixFunction( const ast::Type * type, bool & isVoid ); 24 25 /// Returns declaration with function and array types replaced by equivalent pointer types. 26 /// Sets isVoid to true if type is void. 27 const ast::DeclWithType * fixFunction( const ast::DeclWithType * dwt, bool & isVoid ); 28 const ast::Type * fixFunction( const ast::Type * type, bool & isVoid ); 29 28 30 } // namespace SymTab 29 31 -
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 -
src/SymTab/Mangler.h
re580aa5 rb0845f9 34 34 } 35 35 36 namespace SymTab { 37 namespace Mangler { 38 namespace Encoding { 39 extern const std::string manglePrefix; 40 extern const std::string basicTypes[]; 41 extern const std::map<int, std::string> qualifiers; 36 namespace Mangle { 42 37 43 extern const std::string void_t; 44 extern const std::string zero; 45 extern const std::string one; 38 /// Bitflags for mangle Mode: 39 enum { 40 NoOverrideable = 1 << 0, 41 Type = 1 << 1, 42 NoGenericParams = 1 << 2 43 }; 46 44 47 extern const std::string function; 48 extern const std::string tuple; 49 extern const std::string pointer; 50 extern const std::string array; 51 extern const std::string qualifiedTypeStart; 52 extern const std::string qualifiedTypeEnd; 53 54 extern const std::string forall; 55 extern const std::string typeVariables[]; 56 57 extern const std::string struct_t; 58 extern const std::string union_t; 59 extern const std::string enum_t; 60 extern const std::string type; 61 62 extern const std::string autogen; 63 extern const std::string intrinsic; 45 /// Bitflag type for mangle Mode: 46 struct mangle_flags { 47 union { 48 unsigned int val; 49 struct { 50 bool no_overrideable : 1; 51 bool type : 1; 52 bool no_generic_params : 1; 64 53 }; 65 } // Mangler66 } // SymTab67 68 namespace Mangle {69 /// Bitflags for mangle modes70 enum {71 NoOverrideable = 1 << 0,72 Type = 1 << 1,73 NoGenericParams = 1 << 274 54 }; 75 55 76 /// Bitflag type for mangler modes 77 struct mangle_flags { 78 union { 79 unsigned int val; 80 struct { 81 bool no_overrideable : 1; 82 bool type : 1; 83 bool no_generic_params : 1; 84 }; 85 }; 56 constexpr mangle_flags( unsigned int val ) : val(val) {} 57 }; 86 58 87 constexpr mangle_flags( unsigned int val ) : val(val) {} 88 }; 59 using Mode = bitfield<mangle_flags>; 89 60 90 using Mode = bitfield<mangle_flags>; 61 /// Mangle declaration name. 62 std::string mangle( const ast::Node * decl, Mode mode = {} ); 91 63 92 /// Mangle declaration name. 93 std::string mangle( const ast::Node * decl, Mode mode = {} ); 64 /// Most common mangle configuration for types. 65 static inline std::string mangleType( const ast::Node * type ) { 66 return mangle( type, { NoOverrideable | Type } ); 67 } 94 68 95 /// Most common mangle configuration for types. 96 static inline std::string mangleType( const ast::Node * type ) { 97 return mangle( type, { NoOverrideable | Type } ); 98 } 69 /// The substrings used in name mangling and demangling. 70 namespace Encoding { 71 extern const std::string manglePrefix; 72 extern const std::string basicTypes[]; 73 extern const std::map<int, std::string> qualifiers; 99 74 100 namespace Encoding { 101 using namespace SymTab::Mangler::Encoding; 102 }; 75 extern const std::string void_t; 76 extern const std::string zero; 77 extern const std::string one; 78 79 extern const std::string function; 80 extern const std::string tuple; 81 extern const std::string pointer; 82 extern const std::string array; 83 extern const std::string qualifiedTypeStart; 84 extern const std::string qualifiedTypeEnd; 85 86 extern const std::string forall; 87 extern const std::string typeVariables[]; 88 89 extern const std::string struct_t; 90 extern const std::string union_t; 91 extern const std::string enum_t; 92 extern const std::string type; 93 94 extern const std::string autogen; 95 extern const std::string intrinsic; 96 } 97 103 98 } 104 99 -
src/SymTab/ManglerCommon.cc
re580aa5 rb0845f9 19 19 #include "AST/Type.hpp" 20 20 21 namespace SymTab { 22 namespace Mangler { 23 namespace Encoding { 24 const std::string manglePrefix = "_X"; 21 namespace Mangle { 25 22 26 // GENERATED START, DO NOT EDIT 27 // GENERATED BY BasicTypes-gen.cc 28 // NOTES ON MANGLING: 29 // * Itanium spec says that Float80 encodes to "e" (like LongDouble), but the distinct lengths cause resolution problems. 30 // * Float128 is supposed to encode to "g", but I wanted it to mangle equal to LongDouble. 31 // * Mangling for non-standard complex types is by best guess 32 // * _FloatN is supposed to encode as "DF"N"_"; modified for same reason as above. 33 // * unused mangling identifiers: 34 // - "z" ellipsis 35 // - "Dd" IEEE 754r 64-bit decimal floating point (borrowed for _Float32x) 36 // - "De" IEEE 754r 128-bit decimal floating point 37 // - "Df" IEEE 754r 32-bit decimal floating point 38 // - "Dh" IEEE 754r 16-bit decimal floating point (borrowed for _Float16) 39 // - "DF"N"_" ISO/IEC TS 18661 N-bit binary floating point (_FloatN) 40 // - "Di" char32_t 41 // - "Ds" char16_t 42 const std::string basicTypes[ast::BasicType::NUMBER_OF_BASIC_TYPES] = { 43 "b", // _Bool 44 "c", // char 45 "a", // signed char 46 "h", // unsigned char 47 "s", // signed short int 48 "t", // unsigned short int 49 "i", // signed int 50 "j", // unsigned int 51 "l", // signed long int 52 "m", // unsigned long int 53 "x", // signed long long int 54 "y", // unsigned long long int 55 "n", // __int128 56 "o", // unsigned __int128 57 "DF16_", // _Float16 58 "CDF16_", // _Float16 _Complex 59 "DF32_", // _Float32 60 "CDF32_", // _Float32 _Complex 61 "f", // float 62 "Cf", // float _Complex 63 "DF32x_", // _Float32x 64 "CDF32x_", // _Float32x _Complex 65 "DF64_", // _Float64 66 "CDF64_", // _Float64 _Complex 67 "d", // double 68 "Cd", // double _Complex 69 "DF64x_", // _Float64x 70 "CDF64x_", // _Float64x _Complex 71 "Dq", // __float80 72 "DF128_", // _Float128 73 "CDF128_", // _Float128 _Complex 74 "g", // __float128 75 "e", // long double 76 "Ce", // long double _Complex 77 "DF128x_", // _Float128x 78 "CDF128x_", // _Float128x _Complex 79 }; // basicTypes 80 // GENERATED END 81 static_assert( 82 sizeof(basicTypes)/sizeof(basicTypes[0]) == ast::BasicType::NUMBER_OF_BASIC_TYPES, 83 "Each basic type kind should have a corresponding mangler letter" 84 ); 23 namespace Encoding { 85 24 86 const std::map<int, std::string> qualifiers = { 87 { ast::CV::Const, "K" }, 88 { ast::CV::Volatile, "V" }, 89 { ast::CV::Atomic, "DA" }, // A is array, so need something unique for atmoic. For now, go with multiletter DA 90 { ast::CV::Mutex, "X" }, 91 }; 25 const std::string manglePrefix = "_X"; 92 26 93 const std::string void_t = "v"; 94 const std::string zero = "Z"; 95 const std::string one = "O"; 27 // GENERATED START, DO NOT EDIT 28 // GENERATED BY BasicTypes-gen.cc 29 // NOTES ON MANGLING: 30 // * Itanium spec says that Float80 encodes to "e" (like LongDouble), but the distinct lengths cause resolution problems. 31 // * Float128 is supposed to encode to "g", but I wanted it to mangle equal to LongDouble. 32 // * Mangling for non-standard complex types is by best guess 33 // * _FloatN is supposed to encode as "DF"N"_"; modified for same reason as above. 34 // * unused mangling identifiers: 35 // - "z" ellipsis 36 // - "Dd" IEEE 754r 64-bit decimal floating point (borrowed for _Float32x) 37 // - "De" IEEE 754r 128-bit decimal floating point 38 // - "Df" IEEE 754r 32-bit decimal floating point 39 // - "Dh" IEEE 754r 16-bit decimal floating point (borrowed for _Float16) 40 // - "DF"N"_" ISO/IEC TS 18661 N-bit binary floating point (_FloatN) 41 // - "Di" char32_t 42 // - "Ds" char16_t 43 const std::string basicTypes[ast::BasicType::NUMBER_OF_BASIC_TYPES] = { 44 "b", // _Bool 45 "c", // char 46 "a", // signed char 47 "h", // unsigned char 48 "s", // signed short int 49 "t", // unsigned short int 50 "i", // signed int 51 "j", // unsigned int 52 "l", // signed long int 53 "m", // unsigned long int 54 "x", // signed long long int 55 "y", // unsigned long long int 56 "n", // __int128 57 "o", // unsigned __int128 58 "DF16_", // _Float16 59 "CDF16_", // _Float16 _Complex 60 "DF32_", // _Float32 61 "CDF32_", // _Float32 _Complex 62 "f", // float 63 "Cf", // float _Complex 64 "DF32x_", // _Float32x 65 "CDF32x_", // _Float32x _Complex 66 "DF64_", // _Float64 67 "CDF64_", // _Float64 _Complex 68 "d", // double 69 "Cd", // double _Complex 70 "DF64x_", // _Float64x 71 "CDF64x_", // _Float64x _Complex 72 "Dq", // __float80 73 "DF128_", // _Float128 74 "CDF128_", // _Float128 _Complex 75 "g", // __float128 76 "e", // long double 77 "Ce", // long double _Complex 78 "DF128x_", // _Float128x 79 "CDF128x_", // _Float128x _Complex 80 }; // basicTypes 81 // GENERATED END 82 static_assert( 83 sizeof(basicTypes) / sizeof(basicTypes[0]) == ast::BasicType::NUMBER_OF_BASIC_TYPES, 84 "Each basic type kind should have a corresponding mangler letter" 85 ); 96 86 97 const std::string function = "F"; 98 const std::string tuple = "T";99 const std::string pointer = "P";100 const std::string array = "A";101 const std::string qualifiedTypeStart = "N";102 const std::string qualifiedTypeEnd = "E";87 const std::map<int, std::string> qualifiers = { 88 { ast::CV::Const, "K" }, 89 { ast::CV::Volatile, "V" }, 90 { ast::CV::Atomic, "DA" }, // A is array, so need something unique for atmoic. For now, go with multiletter DA 91 { ast::CV::Mutex, "X" }, 92 }; 103 93 104 const std::string forall = "Q"; 105 const std::string typeVariables[] = { 106 "BD", // dtype 107 "BDS", // dtype + sized 108 "BO", // otype 109 "BF", // ftype 110 "BT", // ttype 111 "BAL", // array length type 112 }; 113 static_assert( 114 sizeof(typeVariables) / sizeof(typeVariables[0]) == ast::TypeDecl::NUMBER_OF_KINDS, 115 "Each type variable kind should have a corresponding mangler prefix" 116 ); 94 const std::string void_t = "v"; 95 const std::string zero = "Z"; 96 const std::string one = "O"; 117 97 118 const std::string struct_t = "S"; 119 const std::string union_t = "U"; 120 const std::string enum_t = "M"; 121 const std::string type = "Y"; 98 const std::string function = "F"; 99 const std::string tuple = "T"; 100 const std::string pointer = "P"; 101 const std::string array = "A"; 102 const std::string qualifiedTypeStart = "N"; 103 const std::string qualifiedTypeEnd = "E"; 122 104 123 const std::string autogen = "autogen__"; 124 const std::string intrinsic = "intrinsic__"; 125 } // namespace Encoding 126 } // namespace Mangler 127 } // namespace SymTab 105 const std::string forall = "Q"; 106 const std::string typeVariables[] = { 107 "BD", // dtype 108 "BDS", // dtype + sized 109 "BO", // otype 110 "BF", // ftype 111 "BT", // ttype 112 "BAL", // array length type 113 }; 114 static_assert( 115 sizeof(typeVariables) / sizeof(typeVariables[0]) == ast::TypeDecl::NUMBER_OF_KINDS, 116 "Each type variable kind should have a corresponding mangler prefix" 117 ); 118 119 const std::string struct_t = "S"; 120 const std::string union_t = "U"; 121 const std::string enum_t = "M"; 122 const std::string type = "Y"; 123 124 const std::string autogen = "autogen__"; 125 const std::string intrinsic = "intrinsic__"; 126 127 } // namespace Encoding 128 129 } // namespace Mangle
Note: See TracChangeset
for help on using the changeset viewer.