source: src/CodeGen/GenType.cpp@ 4d5c5b6a

Last change on this file since 4d5c5b6a was 59fdd0d, checked in by Michael Brooks <mlbrooks@…>, 8 months ago

Improve intermediate code dumps: don't lower zero_t/one_t to int until we're generating final C code; include a comment when we do.

  • Property mode set to 100644
File size: 10.4 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// GenType.cpp --
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 May 20 11:18:00 2022
13// Update Count : 24
14//
15
16#include "GenType.hpp"
17
18#include <cassert> // for assert, assertf
19#include <list> // for _List_iterator, _List_const_iterator
20#include <sstream> // for operator<<, ostringstream, basic_os...
21
22#include "AST/Print.hpp" // for print
23#include "AST/Vector.hpp" // for vector
24#include "CodeGenerator.hpp" // for CodeGenerator
25#include "Common/UniqueName.hpp" // for UniqueName
26
27namespace CodeGen {
28
29namespace {
30
31struct GenType final :
32 public ast::WithShortCircuiting,
33 public ast::WithVisitorRef<GenType> {
34 std::string result;
35 GenType( const std::string &typeString, const Options &options );
36
37 void previsit( ast::Node const * );
38 void postvisit( ast::Node const * );
39
40 void postvisit( ast::FunctionType const * type );
41 void postvisit( ast::VoidType const * type );
42 void postvisit( ast::BasicType const * type );
43 void postvisit( ast::PointerType const * type );
44 void postvisit( ast::ArrayType const * type );
45 void postvisit( ast::ReferenceType const * type );
46 void postvisit( ast::StructInstType const * type );
47 void postvisit( ast::UnionInstType const * type );
48 void postvisit( ast::EnumInstType const * type );
49 void postvisit( ast::TypeInstType const * type );
50 void postvisit( ast::TupleType const * type );
51 void postvisit( ast::VarArgsType const * type );
52 void postvisit( ast::ZeroType const * type );
53 void postvisit( ast::OneType const * type );
54 void postvisit( ast::GlobalScopeType const * type );
55 void postvisit( ast::TraitInstType const * type );
56 void postvisit( ast::TypeofType const * type );
57 void postvisit( ast::VTableType const * type );
58 void postvisit( ast::QualifiedType const * type );
59
60private:
61 void handleQualifiers( ast::Type const *type );
62 std::string handleGeneric( ast::BaseInstType const * type );
63 void genArray( const ast::CV::Qualifiers &qualifiers, ast::Type const *base, ast::Expr const *dimension, bool isVarLen, bool isStatic );
64 std::string genParamList( const ast::vector<ast::Type> & );
65
66 Options options;
67};
68
69GenType::GenType( const std::string &typeString, const Options &options ) : result( typeString ), options( options ) {}
70
71void GenType::previsit( ast::Node const * ) {
72 // Turn off automatic recursion for all nodes, to allow each visitor to
73 // precisely control the order in which its children are visited.
74 visit_children = false;
75}
76
77void GenType::postvisit( ast::Node const * node ) {
78 std::stringstream ss;
79 ast::print( ss, node );
80 assertf( false, "Unhandled node reached in GenType: %s", ss.str().c_str() );
81}
82
83void GenType::postvisit( ast::VoidType const * type ) {
84 result = "void " + result;
85 handleQualifiers( type );
86}
87
88void GenType::postvisit( ast::BasicType const * type ) {
89 ast::BasicKind kind = type->kind;
90 assert( 0 <= kind && kind < ast::BasicKind::NUMBER_OF_BASIC_TYPES );
91 result = std::string( ast::BasicType::typeNames[kind] ) + " " + result;
92 handleQualifiers( type );
93}
94
95void GenType::genArray( const ast::CV::Qualifiers & qualifiers, ast::Type const * base, ast::Expr const *dimension, bool isVarLen, bool isStatic ) {
96 std::ostringstream os;
97 if ( result != "" ) {
98 if ( result[ 0 ] == '*' ) {
99 os << "(" << result << ")";
100 } else {
101 os << result;
102 }
103 }
104 os << "[";
105 if ( isStatic ) {
106 os << "static ";
107 }
108 if ( qualifiers.is_const ) {
109 os << "const ";
110 }
111 if ( qualifiers.is_volatile ) {
112 os << "volatile ";
113 }
114 if ( qualifiers.is_restrict ) {
115 os << "__restrict ";
116 }
117 if ( qualifiers.is_atomic ) {
118 os << "_Atomic ";
119 }
120 if ( dimension != 0 ) {
121 ast::Pass<CodeGenerator>::read( dimension, os, options );
122 } else if ( isVarLen ) {
123 // no dimension expression on a VLA means it came in with the * token
124 os << "*";
125 }
126 os << "]";
127
128 result = os.str();
129
130 base->accept( *visitor );
131}
132
133void GenType::postvisit( ast::PointerType const * type ) {
134 if ( type->isStatic || type->isVarLen || type->dimension ) {
135 genArray( type->qualifiers, type->base, type->dimension, type->isVarLen, type->isStatic );
136 } else {
137 handleQualifiers( type );
138 if ( result[ 0 ] == '?' ) {
139 result = "* " + result;
140 } else {
141 result = "*" + result;
142 }
143 type->base->accept( *visitor );
144 }
145}
146
147void GenType::postvisit( ast::ArrayType const * type ) {
148 genArray( type->qualifiers, type->base, type->dimension, type->isVarLen, type->isStatic );
149}
150
151void GenType::postvisit( ast::ReferenceType const * type ) {
152 assertf( !options.genC, "Reference types should not reach code generation." );
153 handleQualifiers( type );
154 result = "&" + result;
155 type->base->accept( *visitor );
156}
157
158void GenType::postvisit( ast::FunctionType const * type ) {
159 std::ostringstream os;
160
161 if ( result != "" ) {
162 if ( result[ 0 ] == '*' ) {
163 os << "(" << result << ")";
164 } else {
165 os << result;
166 }
167 }
168
169 if ( type->params.empty() ) {
170 if ( !type->isVarArgs ) {
171 os << "(void)";
172 } else if ( options.genC ) {
173 os << "()";
174 } else {
175 os << "(...)";
176 }
177 } else {
178 os << "(" ;
179
180 os << genParamList( type->params );
181
182 if ( type->isVarArgs ) {
183 os << ", ...";
184 }
185 os << ")";
186 }
187
188 result = os.str();
189
190 if ( type->returns.size() == 0 ) {
191 result = "void " + result;
192 } else {
193 type->returns.front()->accept( *visitor );
194 }
195
196 // Add forall clause.
197 if( !type->forall.empty() && !options.genC ) {
198 //assertf( !options.genC, "FunctionDecl type parameters should not reach code generation." );
199 std::ostringstream os;
200 ast::Pass<CodeGenerator> cg( os, options );
201 os << "forall(";
202 cg.core.genCommaList( type->forall );
203 os << ")" << std::endl;
204 result = os.str() + result;
205 }
206}
207
208std::string GenType::handleGeneric( ast::BaseInstType const * type ) {
209 if ( !type->params.empty() ) {
210 std::ostringstream os;
211 ast::Pass<CodeGenerator> cg( os, options );
212 os << "(";
213 cg.core.genCommaList( type->params );
214 os << ") ";
215 return os.str();
216 }
217 return "";
218}
219
220void GenType::postvisit( ast::StructInstType const * type ) {
221 result = type->name + handleGeneric( type ) + " " + result;
222 if ( options.genC ) result = "struct " + result;
223 handleQualifiers( type );
224}
225
226void GenType::postvisit( ast::UnionInstType const * type ) {
227 result = type->name + handleGeneric( type ) + " " + result;
228 if ( options.genC ) result = "union " + result;
229 handleQualifiers( type );
230}
231
232void GenType::postvisit( ast::EnumInstType const * type ) {
233 // if ( type->base && type->base->base ) {
234 // result = genType( type->base->base, result, options );
235 // } else {
236 result = type->name + " " + result;
237 if ( options.genC ) {
238 result = "enum " + result;
239 }
240 // }
241 handleQualifiers( type );
242}
243
244void GenType::postvisit( ast::TypeInstType const * type ) {
245 assertf( !options.genC, "TypeInstType should not reach code generation." );
246 result = type->name + " " + result;
247 handleQualifiers( type );
248}
249
250void GenType::postvisit( ast::TupleType const * type ) {
251 assertf( !options.genC, "TupleType should not reach code generation." );
252 unsigned int i = 0;
253 std::ostringstream os;
254 os << "[";
255 for ( ast::ptr<ast::Type> const & t : type->types ) {
256 i++;
257 os << genType( t, "", options ) << (i == type->size() ? "" : ", ");
258 }
259 os << "] ";
260 result = os.str() + result;
261}
262
263void GenType::postvisit( ast::VarArgsType const * type ) {
264 result = "__builtin_va_list " + result;
265 handleQualifiers( type );
266}
267
268void GenType::postvisit( ast::ZeroType const * type ) {
269 // Ideally these wouldn't hit codegen at all, but should be safe to make them ints.
270 result = ( options.genC ? "long int /*zero_t*/ " : "zero_t " ) + result;
271 handleQualifiers( type );
272}
273
274void GenType::postvisit( ast::OneType const * type ) {
275 // Ideally these wouldn't hit codegen at all, but should be safe to make them ints.
276 result = ( options.genC ? "long int /*one_t*/ " : "one_t " ) + result;
277 handleQualifiers( type );
278}
279
280void GenType::postvisit( ast::GlobalScopeType const * type ) {
281 assertf( !options.genC, "GlobalScopeType should not reach code generation." );
282 handleQualifiers( type );
283}
284
285void GenType::postvisit( ast::TraitInstType const * type ) {
286 assertf( !options.genC, "TraitInstType should not reach code generation." );
287 result = type->name + " " + result;
288 handleQualifiers( type );
289}
290
291void GenType::postvisit( ast::TypeofType const * type ) {
292 std::ostringstream os;
293 os << "typeof(";
294 ast::Pass<CodeGenerator>::read( type->expr.get(), os, options );
295 os << ") " << result;
296 result = os.str();
297 handleQualifiers( type );
298}
299
300void GenType::postvisit( ast::VTableType const * type ) {
301 assertf( !options.genC, "Virtual table types should not reach code generation." );
302 std::ostringstream os;
303 os << "vtable(" << genType( type->base, "", options ) << ") " << result;
304 result = os.str();
305 handleQualifiers( type );
306}
307
308void GenType::postvisit( ast::QualifiedType const * type ) {
309 assertf( !options.genC, "QualifiedType should not reach code generation." );
310 std::ostringstream os;
311 os << genType( type->parent, "", options ) << "." << genType( type->child, "", options ) << result;
312 result = os.str();
313 handleQualifiers( type );
314}
315
316void GenType::handleQualifiers( ast::Type const * type ) {
317 if ( type->is_const() ) {
318 result = "const " + result;
319 }
320 if ( type->is_volatile() ) {
321 result = "volatile " + result;
322 }
323 if ( type->is_restrict() ) {
324 result = "__restrict " + result;
325 }
326 if ( type->is_atomic() ) {
327 result = "_Atomic " + result;
328 }
329}
330
331std::string GenType::genParamList( const ast::vector<ast::Type> & range ) {
332 auto cur = range.begin();
333 auto end = range.end();
334 if ( cur == end ) return "";
335 std::ostringstream oss;
336 UniqueName param( "__param_" );
337 while ( true ) {
338 oss << genType( *cur++, options.genC ? param.newName() : "", options );
339 if ( cur == end ) break;
340 oss << ", ";
341 }
342 return oss.str();
343}
344
345} // namespace
346
347std::string genType( ast::Type const * type, const std::string & base, const Options & options ) {
348 std::ostringstream os;
349 if ( !type->attributes.empty() ) {
350 ast::Pass<CodeGenerator> cg( os, options );
351 cg.core.genAttributes( type->attributes );
352 }
353
354 return os.str() + ast::Pass<GenType>::read( type, base, options );
355}
356
357std::string genTypeNoAttr( ast::Type const * type, const std::string & base, const Options & options ) {
358 return ast::Pass<GenType>::read( type, base, options );
359}
360
361} // namespace CodeGen
362
363// Local Variables: //
364// tab-width: 4 //
365// mode: c++ //
366// compile-command: "make install" //
367// End: //
Note: See TracBrowser for help on using the repository browser.