source: src/GenPoly/ScrubTyVars.cc@ 994028dc

ADT ast-experimental
Last change on this file since 994028dc was 0026d67, checked in by Andrew Beach <ajbeach@…>, 3 years ago

Replaced Mangle::typeMode() with Mangle::mangleType(...), as it is how typeMode() was always used and it is shorter. Various other clean-up in the Mangler files.

  • Property mode set to 100644
File size: 8.6 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 : Fri Oct 7 15:42:00 2022
13// Update Count : 5
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
119enum class ScrubMode {
120 FromMap,
121 DynamicFromMap,
122 All,
123};
124
125struct ScrubTypeVars :
126 public ast::WithGuards,
127 public ast::WithShortCircuiting,
128 public ast::WithVisitorRef<ScrubTypeVars> {
129
130 ScrubTypeVars( ScrubMode m, TypeVarMap 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
147private:
148 ScrubMode const mode;
149 /// Type varriables to scrub.
150 TypeVarMap 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
185ast::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 );
198 if ( typeVar == typeVars->end() ) {
199 return type;
200 }
201
202 switch ( typeVar->second.kind ) {
203 case ::TypeDecl::Dtype:
204 case ::TypeDecl::Ttype:
205 return new ast::PointerType(
206 new ast::VoidType( type->qualifiers ) );
207 case ::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
217ast::Type const * ScrubTypeVars::postvisit( ast::StructInstType const * type ) {
218 return postvisitAggregateType( type );
219}
220
221ast::Type const * ScrubTypeVars::postvisit( ast::UnionInstType const * type ) {
222 return postvisitAggregateType( type );
223}
224
225ast::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::mangleType( dynType ) ) );
230 } else {
231 return expr;
232 }
233}
234
235ast::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::mangleType( dynType ) ) );
240 } else {
241 return expr;
242 }
243}
244
245ast::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
255const ast::Node * scrubTypeVarsBase(
256 const ast::Node * target,
257 ScrubMode mode, const TypeVarMap * 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
269template<>
270ast::Node const * scrubTypeVars<ast::Node>(
271 const ast::Node * target, const TypeVarMap & typeVars ) {
272 return scrubTypeVarsBase( target, ScrubMode::FromMap, &typeVars );
273}
274
275template<>
276ast::Node const * scrubTypeVarsDynamic<ast::Node>(
277 ast::Node const * target, const TypeVarMap & typeVars ) {
278 return scrubTypeVarsBase( target, ScrubMode::DynamicFromMap, &typeVars );
279}
280
281template<>
282ast::Node const * scrubAllTypeVars<ast::Node>( const ast::Node * target ) {
283 return scrubTypeVarsBase( target, ScrubMode::All, nullptr );
284}
285
286} // namespace GenPoly
287
288// Local Variables: //
289// tab-width: 4 //
290// mode: c++ //
291// compile-command: "make install" //
292// End: //
Note: See TracBrowser for help on using the repository browser.