source: src/CodeGen/GenType.cpp @ c92bdcc

Last change on this file since c92bdcc was c92bdcc, checked in by Andrew Beach <ajbeach@…>, 8 weeks ago

Updated the rest of the names in src/ (except for the generated files).

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