source: src/CodeGen/GenType.cpp@ 95707a3

Last change on this file since 95707a3 was db19e1d, checked in by Andrew Beach <ajbeach@…>, 13 months ago

Changed the interpritation of () to be no parameters instead of any parameters. This had a lot of little changes because of this and some nearby clean-up. This includes some changes, including changing some generated functions to be fixed-args instead of variable-args, stripping out the place holder void parameter earlier, but it still shows up earlier in some cases that examine the parser directly. Also had to update the function generation tools. Have only tested with one --arch. Hopefully this all works out.

  • 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.pretty ? "zero_t " : "long int ") + 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.pretty ? "one_t " : "long int ") + 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.