source: src/CodeGen/GenType.cc@ f2898df

Last change on this file since f2898df was 116d7e2, checked in by Andrew Beach <ajbeach@…>, 21 months ago

Small bug fix in code generation. Seems to only come up while generating intermediate code.

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