Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/ScrubTyVars.cc

    r3606fe4 rd978ada  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Aug 19 16:10:00 2022
    13 // Update Count     : 4
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Thu Mar 16 15:44:27 2017
     13// Update Count     : 3
    1414//
    1515
    1616#include <utility>                      // for pair
    1717
    18 #include "AST/Pass.hpp"
    1918#include "GenPoly.h"                    // for mangleType, TyVarMap, alignof...
    2019#include "GenPoly/ErasableScopedMap.h"  // for ErasableScopedMap<>::const_it...
    2120#include "ScrubTyVars.h"
    22 #include "SymTab/Mangler.h"             // for mangle, typeMode
    2321#include "SynTree/Declaration.h"        // for TypeDecl, TypeDecl::Data, Typ...
    2422#include "SynTree/Expression.h"         // for Expression (ptr only), NameExpr
     
    114112                return pointer;
    115113        }
    116 
    117 namespace {
    118 
    119 enum class ScrubMode {
    120         FromMap,
    121         DynamicFromMap,
    122         All,
    123 };
    124 
    125 struct ScrubTypeVars :
    126         public ast::WithGuards,
    127         public ast::WithShortCircuiting,
    128         public ast::WithVisitorRef<ScrubTypeVars> {
    129 
    130         ScrubTypeVars( ScrubMode m, TyVarMap const * tv ) :
    131                         mode ( m ), typeVars( tv ) {}
    132 
    133         void previsit( ast::TypeInstType const * ) { visit_children = false; }
    134         void previsit( ast::StructInstType const * ) { visit_children = false; }
    135         void previsit( ast::UnionInstType const * ) { visit_children = false; }
    136         void previsit( ast::SizeofExpr const * expr ) { primeBaseScrub( expr->type ); }
    137         void previsit( ast::AlignofExpr const * expr ) { primeBaseScrub( expr->type ); }
    138         void previsit( ast::PointerType const * type ) { primeBaseScrub( type->base ); }
    139 
    140         ast::Type const * postvisit( ast::TypeInstType const * type );
    141         ast::Type const * postvisit( ast::StructInstType const * type );
    142         ast::Type const * postvisit( ast::UnionInstType const * type );
    143         ast::Expr const * postvisit( ast::SizeofExpr const * expr );
    144         ast::Expr const * postvisit( ast::AlignofExpr const * expr );
    145         ast::Type const * postvisit( ast::PointerType const * type );
    146 
    147 private:
    148         ScrubMode const mode;
    149         /// Type varriables to scrub.
    150         TyVarMap const * const typeVars;
    151         /// Value cached by primeBaseScrub.
    152         ast::Type const * dynType = nullptr;
    153 
    154         /// Returns the type if it should be scrubbed, nullptr otherwise.
    155         ast::Type const * shouldScrub( ast::Type const * type ) {
    156                 switch ( mode ) {
    157                 case ScrubMode::FromMap:
    158                         return isPolyType( type, *typeVars );
    159                 case ScrubMode::DynamicFromMap:
    160                         return isDynType( type, *typeVars );
    161                 case ScrubMode::All:
    162                         return isPolyType( type );
    163                 default:
    164                         assertf( false, "Invalid ScrubMode in shouldScrub." );
    165                         throw;
    166                 }
    167         }
    168 
    169         void primeBaseScrub( ast::Type const * type ) {
    170                 // Need to determine whether type needs to be scrubbed to
    171                 // determine whether automatic recursion is necessary.
    172                 if ( ast::Type const * t = shouldScrub( type ) ) {
    173                         visit_children = false;
    174                         GuardValue( dynType ) = t;
    175                 }
    176         }
    177 
    178         ast::Type const * postvisitAggregateType(
    179                         ast::BaseInstType const * type ) {
    180                 if ( !shouldScrub( type ) ) return type;
    181                 return new ast::PointerType( new ast::VoidType( type->qualifiers ) );
    182         }
    183 };
    184 
    185 ast::Type const * ScrubTypeVars::postvisit( ast::TypeInstType const * type ) {
    186         // This implies that mode == ScrubMode::All.
    187         if ( !typeVars ) {
    188                 if ( ast::TypeDecl::Ftype == type->kind ) {
    189                         return new ast::PointerType(
    190                                 new ast::FunctionType( ast::FixedArgs ) );
    191                 } else {
    192                         return new ast::PointerType(
    193                                 new ast::VoidType( type->qualifiers ) );
    194                 }
    195         }
    196 
    197         auto typeVar = typeVars->find( type->name );
    198         if ( typeVar == typeVars->end() ) {
    199                 return type;
    200         }
    201 
    202         switch ( typeVar->second.kind ) {
    203         case ast::TypeDecl::Dtype:
    204         case ast::TypeDecl::Ttype:
    205                 return new ast::PointerType(
    206                         new ast::VoidType( type->qualifiers ) );
    207         case ast::TypeDecl::Ftype:
    208                 return new ast::PointerType(
    209                         new ast::FunctionType( ast::VariableArgs ) );
    210         default:
    211                 assertf( false,
    212                         "Unhandled type variable kind: %d", typeVar->second.kind );
    213                 throw; // Just in case the assert is removed, stop here.
    214         }
    215 }
    216 
    217 ast::Type const * ScrubTypeVars::postvisit( ast::StructInstType const * type ) {
    218         return postvisitAggregateType( type );
    219 }
    220 
    221 ast::Type const * ScrubTypeVars::postvisit( ast::UnionInstType const * type ) {
    222         return postvisitAggregateType( type );
    223 }
    224 
    225 ast::Expr const * ScrubTypeVars::postvisit( ast::SizeofExpr const * expr ) {
    226         // sizeof( T ) becomes the _sizeof_T parameter.
    227         if ( dynType ) {
    228                 return new ast::NameExpr( expr->location,
    229                         sizeofName( Mangle::mangle( dynType, Mangle::typeMode() ) ) );
    230         } else {
    231                 return expr;
    232         }
    233 }
    234 
    235 ast::Expr const * ScrubTypeVars::postvisit( ast::AlignofExpr const * expr ) {
    236         // alignof( T ) becomes the _alignof_T parameter.
    237         if ( dynType ) {
    238                 return new ast::NameExpr( expr->location,
    239                         alignofName( Mangle::mangle( dynType, Mangle::typeMode() ) ) );
    240         } else {
    241                 return expr;
    242         }
    243 }
    244 
    245 ast::Type const * ScrubTypeVars::postvisit( ast::PointerType const * type ) {
    246         if ( dynType ) {
    247                 ast::Type * ret = ast::mutate( dynType->accept( *visitor ) );
    248                 ret->qualifiers |= type->qualifiers;
    249                 return ret;
    250         } else {
    251                 return type;
    252         }
    253 }
    254 
    255 const ast::Node * scrubTypeVarsBase(
    256                 const ast::Node * target,
    257                 ScrubMode mode, const TyVarMap * typeVars ) {
    258         if ( ScrubMode::All == mode ) {
    259                 assert( nullptr == typeVars );
    260         } else {
    261                 assert( nullptr != typeVars );
    262         }
    263         ast::Pass<ScrubTypeVars> visitor( mode, typeVars );
    264         return target->accept( visitor );
    265 }
    266 
    267 } // namespace
    268 
    269 template<>
    270 ast::Node const * scrubAllTypeVars<ast::Node>( const ast::Node * target ) {
    271         return scrubTypeVarsBase( target, ScrubMode::All, nullptr );
    272 }
    273 
    274114} // namespace GenPoly
    275115
Note: See TracChangeset for help on using the changeset viewer.