source: src/GenPoly/ScrubTyVars.cc@ 8fd1b7c

ADT ast-experimental
Last change on this file since 8fd1b7c was 2f61765, checked in by Andrew Beach <ajbeach@…>, 3 years ago

Fixed a clang warning and cleaned up the rest of the function.

  • Property mode set to 100644
File size: 7.9 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 --
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#include "SynTree/Declaration.h" // for TypeDecl, TypeDecl::Data, Typ...
24#include "SynTree/Expression.h" // for Expression (ptr only), NameExpr
25#include "SynTree/Mutator.h" // for Mutator
26#include "SynTree/Type.h" // for PointerType, TypeInstType, Type
27
28namespace GenPoly {
29 Type * ScrubTyVars::postmutate( TypeInstType * typeInst ) {
30 if ( ! tyVars ) {
31 if ( typeInst->get_isFtype() ) {
32 delete typeInst;
33 return new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) );
34 } else {
35 PointerType * ret = new PointerType( Type::Qualifiers(), new VoidType( typeInst->get_qualifiers() ) );
36 delete typeInst;
37 return ret;
38 }
39 }
40
41 TyVarMap::const_iterator tyVar = tyVars->find( typeInst->name );
42 if ( tyVar != tyVars->end() ) {
43 switch ( tyVar->second.kind ) {
44 case TypeDecl::Dtype:
45 case TypeDecl::Ttype:
46 {
47 PointerType * ret = new PointerType( Type::Qualifiers(), new VoidType( typeInst->get_qualifiers() ) );
48 delete typeInst;
49 return ret;
50 }
51 case TypeDecl::Ftype:
52 delete typeInst;
53 return new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) );
54 default:
55 assertf(false, "Unhandled tyvar kind: %d", tyVar->second.kind);
56 } // switch
57 } // if
58 return typeInst;
59 }
60
61 Type * ScrubTyVars::mutateAggregateType( Type * ty ) {
62 if ( shouldScrub( ty ) ) {
63 PointerType * ret = new PointerType( Type::Qualifiers(), new VoidType( ty->get_qualifiers() ) );
64 delete ty;
65 return ret;
66 }
67 return ty;
68 }
69
70 Type * ScrubTyVars::postmutate( StructInstType * structInst ) {
71 return mutateAggregateType( structInst );
72 }
73
74 Type * ScrubTyVars::postmutate( UnionInstType * unionInst ) {
75 return mutateAggregateType( unionInst );
76 }
77
78 void ScrubTyVars::primeBaseScrub( Type * type ) {
79 // need to determine whether type needs to be scrubbed to determine whether
80 // automatic recursion is necessary
81 if ( Type * t = shouldScrub( type ) ) {
82 visit_children = false;
83 GuardValue( dynType );
84 dynType = t;
85 }
86 }
87
88 Expression * ScrubTyVars::postmutate( SizeofExpr * szeof ) {
89 // sizeof( T ) => _sizeof_T parameter, which is the size of T
90 if ( dynType ) {
91 Expression *expr = new NameExpr( sizeofName( mangleType( dynType ) ) );
92 return expr;
93 } // if
94 return szeof;
95 }
96
97 Expression * ScrubTyVars::postmutate( AlignofExpr * algnof ) {
98 // alignof( T ) => _alignof_T parameter, which is the alignment of T
99 if ( dynType ) {
100 Expression *expr = new NameExpr( alignofName( mangleType( dynType ) ) );
101 return expr;
102 } // if
103 return algnof;
104 }
105
106 Type * ScrubTyVars::postmutate( PointerType * pointer ) {
107 if ( dynType ) {
108 Type * ret = dynType->acceptMutator( *visitor );
109 ret->get_qualifiers() |= pointer->get_qualifiers();
110 pointer->base = nullptr;
111 delete pointer;
112 return ret;
113 }
114 return pointer;
115 }
116
117namespace {
118
119struct ScrubTypeVars :
120 public ast::WithGuards,
121 public ast::WithShortCircuiting,
122 public ast::WithVisitorRef<ScrubTypeVars> {
123
124 ScrubTypeVars( ScrubMode m, TypeVarMap const * tv ) :
125 mode ( m ), typeVars( tv ) {}
126
127 void previsit( ast::TypeInstType const * ) { visit_children = false; }
128 void previsit( ast::StructInstType const * ) { visit_children = false; }
129 void previsit( ast::UnionInstType const * ) { visit_children = false; }
130 void previsit( ast::SizeofExpr const * expr ) { primeBaseScrub( expr->type ); }
131 void previsit( ast::AlignofExpr const * expr ) { primeBaseScrub( expr->type ); }
132 void previsit( ast::PointerType const * type ) { primeBaseScrub( type->base ); }
133
134 ast::Type const * postvisit( ast::TypeInstType const * type );
135 ast::Type const * postvisit( ast::StructInstType const * type );
136 ast::Type const * postvisit( ast::UnionInstType const * type );
137 ast::Expr const * postvisit( ast::SizeofExpr const * expr );
138 ast::Expr const * postvisit( ast::AlignofExpr const * expr );
139 ast::Type const * postvisit( ast::PointerType const * type );
140
141private:
142 ScrubMode const mode;
143 /// Type varriables to scrub.
144 TypeVarMap const * const typeVars;
145 /// Value cached by primeBaseScrub.
146 ast::Type const * dynType = nullptr;
147
148 /// Returns the type if it should be scrubbed, nullptr otherwise.
149 ast::Type const * shouldScrub( ast::Type const * type ) {
150 switch ( mode ) {
151 case ScrubMode::FromMap:
152 return isPolyType( type, *typeVars );
153 case ScrubMode::DynamicFromMap:
154 return isDynType( type, *typeVars );
155 case ScrubMode::All:
156 return isPolyType( type );
157 default:
158 assertf( false, "Invalid ScrubMode in shouldScrub." );
159 throw;
160 }
161 }
162
163 void primeBaseScrub( ast::Type const * type ) {
164 // Need to determine whether type needs to be scrubbed to
165 // determine whether automatic recursion is necessary.
166 if ( ast::Type const * t = shouldScrub( type ) ) {
167 visit_children = false;
168 GuardValue( dynType ) = t;
169 }
170 }
171
172 ast::Type const * postvisitAggregateType(
173 ast::BaseInstType const * type ) {
174 if ( !shouldScrub( type ) ) return type;
175 return new ast::PointerType( new ast::VoidType( type->qualifiers ) );
176 }
177};
178
179ast::Type const * ScrubTypeVars::postvisit( ast::TypeInstType const * type ) {
180 ast::TypeDecl::Kind kind;
181 // This implies that mode == ScrubMode::All.
182 if ( !typeVars ) {
183 kind = type->kind;
184 } else {
185 // Otherwise, only scrub the type var if it is in map.
186 auto typeVar = typeVars->find( *type );
187 if ( typeVar == typeVars->end() ) {
188 return type;
189 }
190 kind = typeVar->second.kind;
191 }
192
193 switch ( kind ) {
194 case ast::TypeDecl::Dtype:
195 case ast::TypeDecl::Ttype:
196 return new ast::PointerType(
197 new ast::VoidType( type->qualifiers ) );
198 case ast::TypeDecl::Ftype:
199 return new ast::PointerType(
200 new ast::FunctionType( ast::VariableArgs ) );
201 default:
202 assertf( false, "Unhandled type variable kind: %d", kind );
203 throw; // Just in case the assert is removed, stop here.
204 }
205}
206
207ast::Type const * ScrubTypeVars::postvisit( ast::StructInstType const * type ) {
208 return postvisitAggregateType( type );
209}
210
211ast::Type const * ScrubTypeVars::postvisit( ast::UnionInstType const * type ) {
212 return postvisitAggregateType( type );
213}
214
215ast::Expr const * ScrubTypeVars::postvisit( ast::SizeofExpr const * expr ) {
216 // sizeof( T ) becomes the _sizeof_T parameter.
217 if ( dynType ) {
218 return new ast::NameExpr( expr->location,
219 sizeofName( Mangle::mangleType( dynType ) ) );
220 } else {
221 return expr;
222 }
223}
224
225ast::Expr const * ScrubTypeVars::postvisit( ast::AlignofExpr const * expr ) {
226 // alignof( T ) becomes the _alignof_T parameter.
227 if ( dynType ) {
228 return new ast::NameExpr( expr->location,
229 alignofName( Mangle::mangleType( dynType ) ) );
230 } else {
231 return expr;
232 }
233}
234
235ast::Type const * ScrubTypeVars::postvisit( ast::PointerType const * type ) {
236 if ( dynType ) {
237 ast::Type * ret = ast::mutate( dynType->accept( *visitor ) );
238 ret->qualifiers |= type->qualifiers;
239 return ret;
240 } else {
241 return type;
242 }
243}
244
245} // namespace
246
247const ast::Node * scrubTypeVarsBase(
248 const ast::Node * node, const TypeVarMap * typeVars, ScrubMode mode ) {
249 if ( ScrubMode::All == mode ) {
250 assert( nullptr == typeVars );
251 } else {
252 assert( nullptr != typeVars );
253 }
254 ast::Pass<ScrubTypeVars> visitor( mode, typeVars );
255 return node->accept( visitor );
256}
257
258} // namespace GenPoly
259
260// Local Variables: //
261// tab-width: 4 //
262// mode: c++ //
263// compile-command: "make install" //
264// End: //
Note: See TracBrowser for help on using the repository browser.