source: src/CodeGen/GenType.cpp @ 82a5ea2

Last change on this file since 82a5ea2 was db19e1d, checked in by Andrew Beach <ajbeach@…>, 3 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.