source: src/GenPoly/ScrubTypeVars.cpp @ af746cc

Last change on this file since af746cc was d787828d, checked in by Andrew Beach <ajbeach@…>, 7 months ago

Rename the ScrubTyVars? moduel to ScrubTypeVars?. This makes it more consistent with the data types and function names now used.

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