// // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo // // The contents of this file are covered under the licence agreement in the // file "LICENCE" distributed with Cforall. // // Mangler.cc -- // // Author : Richard C. Bilson // Created On : Sun May 17 21:40:29 2015 // Last Modified By : Peter A. Buhr // Last Modified On : Mon Sep 25 15:49:26 2017 // Update Count : 23 // #include "Mangler.h" #include // for copy, transform #include // for assert, assertf #include // for const_mem_fun_t, mem_fun #include // for ostream_iterator, back_insert_ite... #include // for _List_iterator, list, _List_const... #include // for string, char_traits, operator<< #include "CodeGen/OperatorTable.h" // for OperatorInfo, operatorLookup #include "Common/PassVisitor.h" #include "Common/SemanticError.h" // for SemanticError #include "Common/utility.h" // for toString #include "Parser/LinkageSpec.h" // for Spec, isOverridable, AutoGen, Int... #include "SynTree/Declaration.h" // for TypeDecl, DeclarationWithType #include "SynTree/Expression.h" // for TypeExpr, Expression, operator<< #include "SynTree/Type.h" // for Type, ReferenceToType, Type::Fora... namespace SymTab { namespace Mangler { namespace { /// Mangles names to a unique C identifier struct Mangler : public WithShortCircuiting, public WithVisitorRef, public WithGuards { Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams ); Mangler( const Mangler & ) = delete; void previsit( BaseSyntaxNode * ) { visit_children = false; } void postvisit( ObjectDecl * declaration ); void postvisit( FunctionDecl * declaration ); void postvisit( TypeDecl * declaration ); void postvisit( VoidType * voidType ); void postvisit( BasicType * basicType ); void postvisit( PointerType * pointerType ); void postvisit( ArrayType * arrayType ); void postvisit( ReferenceType * refType ); void postvisit( FunctionType * functionType ); void postvisit( StructInstType * aggregateUseType ); void postvisit( UnionInstType * aggregateUseType ); void postvisit( EnumInstType * aggregateUseType ); void postvisit( TypeInstType * aggregateUseType ); void postvisit( TraitInstType * inst ); void postvisit( TupleType * tupleType ); void postvisit( VarArgsType * varArgsType ); void postvisit( ZeroType * zeroType ); void postvisit( OneType * oneType ); void postvisit( QualifiedType * qualType ); std::string get_mangleName() { return mangleName.str(); } private: std::ostringstream mangleName; ///< Mangled name being constructed typedef std::map< std::string, std::pair< int, int > > VarMapType; VarMapType varNums; ///< Map of type variables to indices int nextVarNum; ///< Next type variable index bool isTopLevel; ///< Is the Mangler at the top level bool mangleOverridable; ///< Specially mangle overridable built-in methods bool typeMode; ///< Produce a unique mangled name for a type bool mangleGenericParams; ///< Include generic parameters in name mangling if true bool inFunctionType = false; ///< Include type qualifiers if false. bool inQualifiedType = false; ///< Add start/end delimiters around qualified type void mangleDecl( DeclarationWithType *declaration ); void mangleRef( ReferenceToType *refType, std::string prefix ); void printQualifiers( Type *type ); }; // Mangler } // namespace std::string mangle( BaseSyntaxNode * decl, bool mangleOverridable, bool typeMode, bool mangleGenericParams ) { PassVisitor mangler( mangleOverridable, typeMode, mangleGenericParams ); maybeAccept( decl, mangler ); return mangler.pass.get_mangleName(); } std::string mangleType( Type * ty ) { PassVisitor mangler( false, true, true ); maybeAccept( ty, mangler ); return mangler.pass.get_mangleName(); } std::string mangleConcrete( Type * ty ) { PassVisitor mangler( false, false, false ); maybeAccept( ty, mangler ); return mangler.pass.get_mangleName(); } namespace { Mangler::Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams ) : nextVarNum( 0 ), isTopLevel( true ), mangleOverridable( mangleOverridable ), typeMode( typeMode ), mangleGenericParams( mangleGenericParams ) {} void Mangler::mangleDecl( DeclarationWithType * declaration ) { bool wasTopLevel = isTopLevel; if ( isTopLevel ) { varNums.clear(); nextVarNum = 0; isTopLevel = false; } // if mangleName << Encoding::manglePrefix; CodeGen::OperatorInfo opInfo; if ( operatorLookup( declaration->get_name(), opInfo ) ) { mangleName << opInfo.outputName.size() << opInfo.outputName; } else { mangleName << declaration->name.size() << declaration->name; } // if maybeAccept( declaration->get_type(), *visitor ); if ( mangleOverridable && LinkageSpec::isOverridable( declaration->get_linkage() ) ) { // want to be able to override autogenerated and intrinsic routines, // so they need a different name mangling if ( declaration->get_linkage() == LinkageSpec::AutoGen ) { mangleName << Encoding::autogen; } else if ( declaration->get_linkage() == LinkageSpec::Intrinsic ) { mangleName << Encoding::intrinsic; } else { // if we add another kind of overridable function, this has to change assert( false && "unknown overrideable linkage" ); } // if } isTopLevel = wasTopLevel; } void Mangler::postvisit( ObjectDecl * declaration ) { mangleDecl( declaration ); } void Mangler::postvisit( FunctionDecl * declaration ) { mangleDecl( declaration ); } void Mangler::postvisit( VoidType * voidType ) { printQualifiers( voidType ); mangleName << Encoding::void_t; } void Mangler::postvisit( BasicType * basicType ) { printQualifiers( basicType ); assertf( basicType->get_kind() < BasicType::NUMBER_OF_BASIC_TYPES, "Unhandled basic type: %d", basicType->get_kind() ); mangleName << Encoding::basicTypes[ basicType->get_kind() ]; } void Mangler::postvisit( PointerType * pointerType ) { printQualifiers( pointerType ); // mangle void (*f)() and void f() to the same name to prevent overloading on functions and function pointers if ( ! dynamic_cast( pointerType->base ) ) mangleName << Encoding::pointer; maybeAccept( pointerType->base, *visitor ); } void Mangler::postvisit( ArrayType * arrayType ) { // TODO: encode dimension printQualifiers( arrayType ); mangleName << Encoding::array << "0"; maybeAccept( arrayType->base, *visitor ); } void Mangler::postvisit( ReferenceType * refType ) { // don't print prefix (e.g. 'R') for reference types so that references and non-references do not overload. // Further, do not print the qualifiers for a reference type (but do run printQualifers because of TypeDecls, etc.), // by pretending every reference type is a function parameter. GuardValue( inFunctionType ); inFunctionType = true; printQualifiers( refType ); maybeAccept( refType->base, *visitor ); } namespace { inline std::list< Type* > getTypes( const std::list< DeclarationWithType* > decls ) { std::list< Type* > ret; std::transform( decls.begin(), decls.end(), std::back_inserter( ret ), std::mem_fun( &DeclarationWithType::get_type ) ); return ret; } } void Mangler::postvisit( FunctionType * functionType ) { printQualifiers( functionType ); mangleName << Encoding::function; // turn on inFunctionType so that printQualifiers does not print most qualifiers for function parameters, // since qualifiers on outermost parameter type do not differentiate function types, e.g., // void (*)(const int) and void (*)(int) are the same type, but void (*)(const int *) and void (*)(int *) are different GuardValue( inFunctionType ); inFunctionType = true; std::list< Type* > returnTypes = getTypes( functionType->returnVals ); if (returnTypes.empty()) mangleName << Encoding::void_t; else acceptAll( returnTypes, *visitor ); mangleName << "_"; std::list< Type* > paramTypes = getTypes( functionType->parameters ); acceptAll( paramTypes, *visitor ); mangleName << "_"; } void Mangler::mangleRef( ReferenceToType * refType, std::string prefix ) { printQualifiers( refType ); mangleName << prefix << refType->name.length() << refType->name; if ( mangleGenericParams ) { std::list< Expression* >& params = refType->parameters; if ( ! params.empty() ) { mangleName << "_"; for ( std::list< Expression* >::const_iterator param = params.begin(); param != params.end(); ++param ) { TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param ); assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString(*param)); maybeAccept( paramType->type, *visitor ); } mangleName << "_"; } } } void Mangler::postvisit( StructInstType * aggregateUseType ) { mangleRef( aggregateUseType, Encoding::struct_t ); } void Mangler::postvisit( UnionInstType * aggregateUseType ) { mangleRef( aggregateUseType, Encoding::union_t ); } void Mangler::postvisit( EnumInstType * aggregateUseType ) { mangleRef( aggregateUseType, Encoding::enum_t ); } void Mangler::postvisit( TypeInstType * typeInst ) { VarMapType::iterator varNum = varNums.find( typeInst->get_name() ); if ( varNum == varNums.end() ) { mangleRef( typeInst, Encoding::type ); } else { printQualifiers( typeInst ); // Note: Can't use name here, since type variable names do not actually disambiguate a function, e.g. // forall(dtype T) void f(T); // forall(dtype S) void f(S); // are equivalent and should mangle the same way. This is accomplished by numbering the type variables when they // are first found and prefixing with the appropriate encoding for the type class. assertf( varNum->second.second < TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", varNum->second.second ); mangleName << Encoding::typeVariables[varNum->second.second] << varNum->second.first; } // if } void Mangler::postvisit( TraitInstType * inst ) { printQualifiers( inst ); mangleName << inst->name.size() << inst->name; } void Mangler::postvisit( TupleType * tupleType ) { printQualifiers( tupleType ); mangleName << Encoding::tuple << tupleType->types.size(); acceptAll( tupleType->types, *visitor ); } void Mangler::postvisit( VarArgsType * varArgsType ) { printQualifiers( varArgsType ); static const std::string vargs = "__builtin_va_list"; mangleName << Encoding::type << vargs.size() << vargs; } void Mangler::postvisit( ZeroType * ) { mangleName << Encoding::zero; } void Mangler::postvisit( OneType * ) { mangleName << Encoding::one; } void Mangler::postvisit( QualifiedType * qualType ) { bool inqual = inQualifiedType; if (! inqual ) { // N marks the start of a qualified type inQualifiedType = true; mangleName << Encoding::qualifiedTypeStart; } maybeAccept( qualType->parent, *visitor ); maybeAccept( qualType->child, *visitor ); if ( ! inqual ) { // E marks the end of a qualified type inQualifiedType = false; mangleName << Encoding::qualifiedTypeEnd; } } void Mangler::postvisit( TypeDecl * decl ) { // TODO: is there any case where mangling a TypeDecl makes sense? If so, this code needs to be // fixed to ensure that two TypeDecls mangle to the same name when they are the same type and vice versa. // Note: The current scheme may already work correctly for this case, I have not thought about this deeply // and the case has not yet come up in practice. Alternatively, if not then this code can be removed // aside from the assert false. assertf(false, "Mangler should not visit typedecl: %s", toCString(decl)); assertf( decl->get_kind() < TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->get_kind() ); mangleName << Encoding::typeVariables[ decl->get_kind() ] << ( decl->name.length() ) << decl->name; } __attribute__((unused)) void printVarMap( const std::map< std::string, std::pair< int, int > > &varMap, std::ostream &os ) { for ( std::map< std::string, std::pair< int, int > >::const_iterator i = varMap.begin(); i != varMap.end(); ++i ) { os << i->first << "(" << i->second.first << "/" << i->second.second << ")" << std::endl; } // for } void Mangler::printQualifiers( Type * type ) { // skip if not including qualifiers if ( typeMode ) return; if ( ! type->get_forall().empty() ) { std::list< std::string > assertionNames; int dcount = 0, fcount = 0, vcount = 0, acount = 0; mangleName << Encoding::forall; for ( Type::ForallList::iterator i = type->forall.begin(); i != type->forall.end(); ++i ) { switch ( (*i)->get_kind() ) { case TypeDecl::Dtype: dcount++; break; case TypeDecl::Ftype: fcount++; break; case TypeDecl::Ttype: vcount++; break; default: assert( false ); } // switch varNums[ (*i)->name ] = std::pair< int, int >( nextVarNum++, (int)(*i)->get_kind() ); for ( std::list< DeclarationWithType* >::iterator assert = (*i)->assertions.begin(); assert != (*i)->assertions.end(); ++assert ) { PassVisitor sub_mangler( mangleOverridable, typeMode, mangleGenericParams ); sub_mangler.pass.nextVarNum = nextVarNum; sub_mangler.pass.isTopLevel = false; sub_mangler.pass.varNums = varNums; (*assert)->accept( sub_mangler ); assertionNames.push_back( sub_mangler.pass.mangleName.str() ); acount++; } // for } // for mangleName << dcount << "_" << fcount << "_" << vcount << "_" << acount << "_"; std::copy( assertionNames.begin(), assertionNames.end(), std::ostream_iterator< std::string >( mangleName, "" ) ); mangleName << "_"; } // if if ( ! inFunctionType ) { // these qualifiers do not distinguish the outermost type of a function parameter if ( type->get_const() ) { mangleName << Encoding::qualifiers.at(Type::Const); } // if if ( type->get_volatile() ) { mangleName << Encoding::qualifiers.at(Type::Volatile); } // if // Removed due to restrict not affecting function compatibility in GCC // if ( type->get_isRestrict() ) { // mangleName << "E"; // } // if if ( type->get_atomic() ) { mangleName << Encoding::qualifiers.at(Type::Atomic); } // if } if ( type->get_mutex() ) { mangleName << Encoding::qualifiers.at(Type::Mutex); } // if if ( type->get_lvalue() ) { // mangle based on whether the type is lvalue, so that the resolver can differentiate lvalues and rvalues mangleName << Encoding::qualifiers.at(Type::Lvalue); } if ( inFunctionType ) { // turn off inFunctionType so that types can be differentiated for nested qualifiers GuardValue( inFunctionType ); inFunctionType = false; } } } // namespace } // namespace Mangler } // namespace SymTab // Local Variables: // // tab-width: 4 // // mode: c++ // // compile-command: "make install" // // End: //