// // 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 { Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams ); Mangler( const Mangler & ); 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( TupleType * tupleType ); void postvisit( VarArgsType * varArgsType ); void postvisit( ZeroType * zeroType ); void postvisit( OneType * oneType ); 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 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 << "__"; CodeGen::OperatorInfo opInfo; if ( operatorLookup( declaration->get_name(), opInfo ) ) { mangleName << opInfo.outputName; } else { mangleName << declaration->get_name(); } // if mangleName << "__"; 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 << "autogen__"; } else if ( declaration->get_linkage() == LinkageSpec::Intrinsic ) { mangleName << "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 << "v"; } void Mangler::postvisit( BasicType * basicType ) { static const char *btLetter[] = { "b", // Bool "c", // Char "Sc", // SignedChar "Uc", // UnsignedChar "s", // ShortSignedInt "Us", // ShortUnsignedInt "i", // SignedInt "Ui", // UnsignedInt "l", // LongSignedInt "Ul", // LongUnsignedInt "q", // LongLongSignedInt "Uq", // LongLongUnsignedInt "f", // Float "d", // Double "r", // LongDouble "Xf", // FloatComplex "Xd", // DoubleComplex "Xr", // LongDoubleComplex "If", // FloatImaginary "Id", // DoubleImaginary "Ir", // LongDoubleImaginary "w", // SignedInt128 "Uw", // UnsignedInt128 }; printQualifiers( basicType ); mangleName << btLetter[ basicType->get_kind() ]; } void Mangler::postvisit( PointerType * pointerType ) { printQualifiers( pointerType ); mangleName << "P"; maybeAccept( pointerType->get_base(), *visitor ); } void Mangler::postvisit( ArrayType * arrayType ) { // TODO: encode dimension printQualifiers( arrayType ); mangleName << "A0"; maybeAccept( arrayType->get_base(), *visitor ); } void Mangler::postvisit( ReferenceType * refType ) { printQualifiers( refType ); mangleName << "R"; maybeAccept( refType->get_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 << "F"; std::list< Type* > returnTypes = getTypes( functionType->get_returnVals() ); acceptAll( returnTypes, *visitor ); mangleName << "_"; std::list< Type* > paramTypes = getTypes( functionType->get_parameters() ); acceptAll( paramTypes, *visitor ); mangleName << "_"; } void Mangler::mangleRef( ReferenceToType * refType, std::string prefix ) { printQualifiers( refType ); mangleName << ( refType->get_name().length() + prefix.length() ) << prefix << refType->get_name(); if ( mangleGenericParams ) { std::list< Expression* >& params = refType->get_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", toString(*param).c_str()); maybeAccept( paramType->get_type(), *visitor ); } mangleName << "_"; } } } void Mangler::postvisit( StructInstType * aggregateUseType ) { mangleRef( aggregateUseType, "s" ); } void Mangler::postvisit( UnionInstType * aggregateUseType ) { mangleRef( aggregateUseType, "u" ); } void Mangler::postvisit( EnumInstType * aggregateUseType ) { mangleRef( aggregateUseType, "e" ); } void Mangler::postvisit( TypeInstType * typeInst ) { VarMapType::iterator varNum = varNums.find( typeInst->get_name() ); if ( varNum == varNums.end() ) { mangleRef( typeInst, "t" ); } else { printQualifiers( typeInst ); std::ostringstream numStream; numStream << varNum->second.first; switch ( (TypeDecl::Kind )varNum->second.second ) { case TypeDecl::Dtype: mangleName << "d"; break; case TypeDecl::Ftype: mangleName << "f"; break; case TypeDecl::Ttype: mangleName << "tVARGS"; break; default: assert( false ); } // switch mangleName << numStream.str(); } // if } void Mangler::postvisit( TupleType * tupleType ) { printQualifiers( tupleType ); mangleName << "T"; acceptAll( tupleType->types, *visitor ); mangleName << "_"; } void Mangler::postvisit( VarArgsType * varArgsType ) { printQualifiers( varArgsType ); mangleName << "VARGS"; } void Mangler::postvisit( ZeroType * ) { mangleName << "Z"; } void Mangler::postvisit( OneType * ) { mangleName << "O"; } void Mangler::postvisit( TypeDecl * decl ) { static const char *typePrefix[] = { "BT", "BD", "BF" }; mangleName << typePrefix[ decl->get_kind() ] << ( decl->name.length() + 1 ) << 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 tcount = 0, dcount = 0, fcount = 0, vcount = 0; mangleName << "A"; 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() ); } // for } // for mangleName << tcount << "_" << dcount << "_" << fcount << "_" << vcount << "_"; std::copy( assertionNames.begin(), assertionNames.end(), std::ostream_iterator< std::string >( mangleName, "" ) ); mangleName << "_"; } // if if ( type->get_const() ) { mangleName << "C"; } // if if ( type->get_volatile() ) { mangleName << "V"; } // if if ( type->get_mutex() ) { mangleName << "M"; } // if // Removed due to restrict not affecting function compatibility in GCC // if ( type->get_isRestrict() ) { // mangleName << "E"; // } // if if ( type->get_lvalue() ) { // mangle based on whether the type is lvalue, so that the resolver can differentiate lvalues and rvalues mangleName << "L"; } if ( type->get_atomic() ) { mangleName << "A"; } // if } } // namespace } // namespace Mangler } // namespace SymTab // Local Variables: // // tab-width: 4 // // mode: c++ // // compile-command: "make install" // // End: //