source: src/CodeGen/GenType.cpp @ 0097d08

Last change on this file since 0097d08 was 31f4837, checked in by JiadaL <j82liang@…>, 6 months ago

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

  • 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 << "()";
172                } else {
173                        os << "(void)";
174                }
175        } else {
176                os << "(" ;
177
178                os << genParamList( type->params );
179
180                if ( type->isVarArgs ) {
181                        os << ", ...";
182                }
183                os << ")";
184        }
185
186        result = os.str();
187
188        if ( type->returns.size() == 0 ) {
189                result = "void " + result;
190        } else {
191                type->returns.front()->accept( *visitor );
192        }
193
194        // Add forall clause.
195        if( !type->forall.empty() && !options.genC ) {
196                //assertf( !options.genC, "FunctionDecl type parameters should not reach code generation." );
197                std::ostringstream os;
198                ast::Pass<CodeGenerator> cg( os, options );
199                os << "forall(";
200                cg.core.genCommaList( type->forall );
201                os << ")" << std::endl;
202                result = os.str() + result;
203        }
204}
205
206std::string GenType::handleGeneric( ast::BaseInstType const * type ) {
207        if ( !type->params.empty() ) {
208                std::ostringstream os;
209                ast::Pass<CodeGenerator> cg( os, options );
210                os << "(";
211                cg.core.genCommaList( type->params );
212                os << ") ";
213                return os.str();
214        }
215        return "";
216}
217
218void GenType::postvisit( ast::StructInstType const * type )  {
219        result = type->name + handleGeneric( type ) + " " + result;
220        if ( options.genC ) result = "struct " + result;
221        handleQualifiers( type );
222}
223
224void GenType::postvisit( ast::UnionInstType const * type ) {
225        result = type->name + handleGeneric( type ) + " " + result;
226        if ( options.genC ) result = "union " + result;
227        handleQualifiers( type );
228}
229
230void GenType::postvisit( ast::EnumInstType const * type ) {
231        // if ( type->base && type->base->base ) {
232        //      result = genType( type->base->base, result, options );
233        // } else {
234                result = type->name + " " + result;
235                if ( options.genC ) {
236                        result = "enum " + result;
237                }
238        // }
239        handleQualifiers( type );
240}
241
242void GenType::postvisit( ast::TypeInstType const * type ) {
243        assertf( !options.genC, "TypeInstType should not reach code generation." );
244        result = type->name + " " + result;
245        handleQualifiers( type );
246}
247
248void GenType::postvisit( ast::TupleType const * type ) {
249        assertf( !options.genC, "TupleType should not reach code generation." );
250        unsigned int i = 0;
251        std::ostringstream os;
252        os << "[";
253        for ( ast::ptr<ast::Type> const & t : type->types ) {
254                i++;
255                os << genType( t, "", options ) << (i == type->size() ? "" : ", ");
256        }
257        os << "] ";
258        result = os.str() + result;
259}
260
261void GenType::postvisit( ast::VarArgsType const * type ) {
262        result = "__builtin_va_list " + result;
263        handleQualifiers( type );
264}
265
266void GenType::postvisit( ast::ZeroType const * type ) {
267        // Ideally these wouldn't hit codegen at all, but should be safe to make them ints.
268        result = (options.pretty ? "zero_t " : "long int ") + result;
269        handleQualifiers( type );
270}
271
272void GenType::postvisit( ast::OneType const * type ) {
273        // Ideally these wouldn't hit codegen at all, but should be safe to make them ints.
274        result = (options.pretty ? "one_t " : "long int ") + result;
275        handleQualifiers( type );
276}
277
278void GenType::postvisit( ast::GlobalScopeType const * type ) {
279        assertf( !options.genC, "GlobalScopeType should not reach code generation." );
280        handleQualifiers( type );
281}
282
283void GenType::postvisit( ast::TraitInstType const * type ) {
284        assertf( !options.genC, "TraitInstType should not reach code generation." );
285        result = type->name + " " + result;
286        handleQualifiers( type );
287}
288
289void GenType::postvisit( ast::TypeofType const * type ) {
290        std::ostringstream os;
291        os << "typeof(";
292        ast::Pass<CodeGenerator>::read( type->expr.get(), os, options );
293        os << ") " << result;
294        result = os.str();
295        handleQualifiers( type );
296}
297
298void GenType::postvisit( ast::VTableType const * type ) {
299        assertf( !options.genC, "Virtual table types should not reach code generation." );
300        std::ostringstream os;
301        os << "vtable(" << genType( type->base, "", options ) << ") " << result;
302        result = os.str();
303        handleQualifiers( type );
304}
305
306void GenType::postvisit( ast::QualifiedType const * type ) {
307        assertf( !options.genC, "QualifiedType should not reach code generation." );
308        std::ostringstream os;
309        os << genType( type->parent, "", options ) << "." << genType( type->child, "", options ) << result;
310        result = os.str();
311        handleQualifiers( type );
312}
313
314void GenType::handleQualifiers( ast::Type const * type ) {
315        if ( type->is_const() ) {
316                result = "const " + result;
317        }
318        if ( type->is_volatile() ) {
319                result = "volatile " + result;
320        }
321        if ( type->is_restrict() ) {
322                result = "__restrict " + result;
323        }
324        if ( type->is_atomic() ) {
325                result = "_Atomic " + result;
326        }
327}
328
329std::string GenType::genParamList( const ast::vector<ast::Type> & range ) {
330        auto cur = range.begin();
331        auto end = range.end();
332        if ( cur == end ) return "";
333        std::ostringstream oss;
334        UniqueName param( "__param_" );
335        while ( true ) {
336                oss << genType( *cur++, options.genC ? param.newName() : "", options );
337                if ( cur == end ) break;
338                oss << ", ";
339        }
340        return oss.str();
341}
342
343} // namespace
344
345std::string genType( ast::Type const * type, const std::string & base, const Options & options ) {
346        std::ostringstream os;
347        if ( !type->attributes.empty() ) {
348                ast::Pass<CodeGenerator> cg( os, options );
349                cg.core.genAttributes( type->attributes );
350        }
351
352        return os.str() + ast::Pass<GenType>::read( type, base, options );
353}
354
355std::string genTypeNoAttr( ast::Type const * type, const std::string & base, const Options & options ) {
356        return ast::Pass<GenType>::read( type, base, options );
357}
358
359} // namespace CodeGen
360
361// Local Variables: //
362// tab-width: 4 //
363// mode: c++ //
364// compile-command: "make install" //
365// End: //
Note: See TracBrowser for help on using the repository browser.