source: src/GenPoly/ScrubTyVars.cc @ f22b170b

Last change on this file since f22b170b was b8b5535, checked in by Andrew Beach <ajbeach@…>, 9 months ago

Major round of clean-up in the GenPoly? directory.

  • Property mode set to 100644
File size: 5.1 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// ScrubTyVars.cc -- Remove polymorphic types.
8//
9// Author           : Richard C. Bilson
10// Created On       : Mon May 18 07:44:20 2015
11// Last Modified By : Andrew Beach
12// Last Modified On : Wed Dec  7 17:01:00 2022
13// Update Count     : 6
14//
15
16#include <utility>                      // for pair
17
18#include "AST/Pass.hpp"
19#include "GenPoly.h"                    // for mangleType, TyVarMap, alignof...
20#include "GenPoly/ErasableScopedMap.h"  // for ErasableScopedMap<>::const_it...
21#include "ScrubTyVars.h"
22#include "SymTab/Mangler.h"             // for mangleType
23
24namespace GenPoly {
25
26namespace {
27
28struct ScrubTypeVars :
29                public ast::WithGuards,
30                public ast::WithShortCircuiting,
31                public ast::WithVisitorRef<ScrubTypeVars> {
32
33        ScrubTypeVars( ScrubMode m, TypeVarMap const * tv ) :
34                        mode ( m ), typeVars( tv ) {}
35
36        void previsit( ast::TypeInstType const * ) { visit_children = false; }
37        void previsit( ast::StructInstType const * ) { visit_children = false; }
38        void previsit( ast::UnionInstType const * ) { visit_children = false; }
39        void previsit( ast::SizeofExpr const * expr ) { primeBaseScrub( expr->type ); }
40        void previsit( ast::AlignofExpr const * expr ) { primeBaseScrub( expr->type ); }
41        void previsit( ast::PointerType const * type ) { primeBaseScrub( type->base ); }
42
43        ast::Type const * postvisit( ast::TypeInstType const * type );
44        ast::Type const * postvisit( ast::StructInstType const * type );
45        ast::Type const * postvisit( ast::UnionInstType const * type );
46        ast::Expr const * postvisit( ast::SizeofExpr const * expr );
47        ast::Expr const * postvisit( ast::AlignofExpr const * expr );
48        ast::Type const * postvisit( ast::PointerType const * type );
49
50private:
51        ScrubMode const mode;
52        /// Type varriables to scrub.
53        TypeVarMap const * const typeVars;
54        /// Value cached by primeBaseScrub.
55        ast::Type const * dynType = nullptr;
56
57        /// Returns the type if it should be scrubbed, nullptr otherwise.
58        ast::Type const * shouldScrub( ast::Type const * type ) {
59                switch ( mode ) {
60                case ScrubMode::FromMap:
61                        return isPolyType( type, *typeVars );
62                case ScrubMode::DynamicFromMap:
63                        return isDynType( type, *typeVars );
64                case ScrubMode::All:
65                        return isPolyType( type );
66                default:
67                        assertf( false, "Invalid ScrubMode in shouldScrub." );
68                        throw;
69                }
70        }
71
72        void primeBaseScrub( ast::Type const * type ) {
73                // Need to determine whether type needs to be scrubbed to
74                // determine whether automatic recursion is necessary.
75                if ( ast::Type const * t = shouldScrub( type ) ) {
76                        visit_children = false;
77                        GuardValue( dynType ) = t;
78                }
79        }
80
81        ast::Type const * postvisitAggregateType(
82                        ast::BaseInstType const * type ) {
83                if ( !shouldScrub( type ) ) return type;
84                return new ast::PointerType( new ast::VoidType( type->qualifiers ) );
85        }
86};
87
88ast::Type const * ScrubTypeVars::postvisit( ast::TypeInstType const * type ) {
89        ast::TypeDecl::Kind kind;
90        // This implies that mode == ScrubMode::All.
91        if ( !typeVars ) {
92                kind = type->kind;
93        } else {
94                // Otherwise, only scrub the type var if it is in map.
95                auto typeVar = typeVars->find( *type );
96                if ( typeVar == typeVars->end() ) {
97                        return type;
98                }
99                kind = typeVar->second.kind;
100        }
101
102        switch ( kind ) {
103        case ast::TypeDecl::Dtype:
104        case ast::TypeDecl::Ttype:
105                return new ast::PointerType(
106                        new ast::VoidType( type->qualifiers ) );
107        case ast::TypeDecl::Ftype:
108                return new ast::PointerType(
109                        new ast::FunctionType( ast::VariableArgs ) );
110        default:
111                assertf( false, "Unhandled type variable kind: %d", kind );
112                throw; // Just in case the assert is removed, stop here.
113        }
114}
115
116ast::Type const * ScrubTypeVars::postvisit( ast::StructInstType const * type ) {
117        return postvisitAggregateType( type );
118}
119
120ast::Type const * ScrubTypeVars::postvisit( ast::UnionInstType const * type ) {
121        return postvisitAggregateType( type );
122}
123
124ast::Expr const * ScrubTypeVars::postvisit( ast::SizeofExpr const * expr ) {
125        // sizeof( T ) becomes the _sizeof_T parameter.
126        if ( dynType ) {
127                return new ast::NameExpr( expr->location,
128                        sizeofName( Mangle::mangleType( dynType ) ) );
129        } else {
130                return expr;
131        }
132}
133
134ast::Expr const * ScrubTypeVars::postvisit( ast::AlignofExpr const * expr ) {
135        // alignof( T ) becomes the _alignof_T parameter.
136        if ( dynType ) {
137                return new ast::NameExpr( expr->location,
138                        alignofName( Mangle::mangleType( dynType ) ) );
139        } else {
140                return expr;
141        }
142}
143
144ast::Type const * ScrubTypeVars::postvisit( ast::PointerType const * type ) {
145        if ( dynType ) {
146                ast::Type * ret = ast::mutate( dynType->accept( *visitor ) );
147                ret->qualifiers |= type->qualifiers;
148                return ret;
149        } else {
150                return type;
151        }
152}
153
154} // namespace
155
156const ast::Node * scrubTypeVarsBase(
157                const ast::Node * node, const TypeVarMap * typeVars, ScrubMode mode ) {
158        if ( ScrubMode::All == mode ) {
159                assert( nullptr == typeVars );
160        } else {
161                assert( nullptr != typeVars );
162        }
163        ast::Pass<ScrubTypeVars> visitor( mode, typeVars );
164        return node->accept( visitor );
165}
166
167} // namespace GenPoly
168
169// Local Variables: //
170// tab-width: 4 //
171// mode: c++ //
172// compile-command: "make install" //
173// End: //
Note: See TracBrowser for help on using the repository browser.