source: src/CodeGen/GenType.cc @ 5bf685f

Last change on this file since 5bf685f was 116d7e2, checked in by Andrew Beach <ajbeach@…>, 7 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
RevLine 
[51587aa]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//
[486341f]7// GenType.cc --
[51587aa]8//
9// Author           : Richard C. Bilson
10// Created On       : Mon May 18 07:44:20 2015
[42a36d9]11// Last Modified By : Andrew Beach
[c715e5f]12// Last Modified On : Fri May 20 11:18:00 2022
13// Update Count     : 24
[51587aa]14//
[3268a58]15#include "GenType.h"
[51587aa]16
[bf2438c]17#include <cassert>                // for assert, assertf
18#include <list>                   // for _List_iterator, _List_const_iterator
19#include <sstream>                // for operator<<, ostringstream, basic_os...
[51b7345]20
[8941b6b]21#include "AST/Print.hpp"          // for print
22#include "AST/Vector.hpp"         // for vector
[83fd57d]23#include "CodeGenerator.hpp"      // for CodeGenerator
[934fa0f]24#include "Common/UniqueName.h"    // for UniqueName
[51b7345]25
26namespace CodeGen {
[8941b6b]27
28namespace {
29
[0bd3faf]30struct GenType final :
[8941b6b]31                public ast::WithShortCircuiting,
[0bd3faf]32                public ast::WithVisitorRef<GenType> {
[8941b6b]33        std::string result;
[0bd3faf]34        GenType( const std::string &typeString, const Options &options );
[8941b6b]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
[0bd3faf]68GenType::GenType( const std::string &typeString, const Options &options ) : result( typeString ), options( options ) {}
[8941b6b]69
[0bd3faf]70void GenType::previsit( ast::Node const * ) {
[8941b6b]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
[0bd3faf]76void GenType::postvisit( ast::Node const * node ) {
[8941b6b]77        std::stringstream ss;
78        ast::print( ss, node );
79        assertf( false, "Unhandled node reached in GenType: %s", ss.str().c_str() );
80}
81
[0bd3faf]82void GenType::postvisit( ast::VoidType const * type ) {
[8941b6b]83        result = "void " + result;
84        handleQualifiers( type );
85}
86
[0bd3faf]87void GenType::postvisit( ast::BasicType const * type ) {
[8941b6b]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
[0bd3faf]94void GenType::genArray( const ast::CV::Qualifiers & qualifiers, ast::Type const * base, ast::Expr const *dimension, bool isVarLen, bool isStatic ) {
[8941b6b]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 ) {
[0bd3faf]120                ast::Pass<CodeGenerator>::read( dimension, os, options );
[8941b6b]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
[0bd3faf]132void GenType::postvisit( ast::PointerType const * type ) {
[8941b6b]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
[0bd3faf]146void GenType::postvisit( ast::ArrayType const * type ) {
[8941b6b]147        genArray( type->qualifiers, type->base, type->dimension, type->isVarLen, type->isStatic );
148}
149
[0bd3faf]150void GenType::postvisit( ast::ReferenceType const * type ) {
[8941b6b]151        assertf( !options.genC, "Reference types should not reach code generation." );
152        handleQualifiers( type );
153        result = "&" + result;
154        type->base->accept( *visitor );
155}
156
[0bd3faf]157void GenType::postvisit( ast::FunctionType const * type ) {
[8941b6b]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;
[0bd3faf]197                ast::Pass<CodeGenerator> cg( os, options );
[8941b6b]198                os << "forall(";
199                cg.core.genCommaList( type->forall );
200                os << ")" << std::endl;
201                result = os.str() + result;
202        }
203}
204
[0bd3faf]205std::string GenType::handleGeneric( ast::BaseInstType const * type ) {
[8941b6b]206        if ( !type->params.empty() ) {
207                std::ostringstream os;
[0bd3faf]208                ast::Pass<CodeGenerator> cg( os, options );
[8941b6b]209                os << "(";
210                cg.core.genCommaList( type->params );
211                os << ") ";
212                return os.str();
213        }
214        return "";
215}
216
[0bd3faf]217void GenType::postvisit( ast::StructInstType const * type )  {
[8941b6b]218        result = type->name + handleGeneric( type ) + " " + result;
219        if ( options.genC ) result = "struct " + result;
220        handleQualifiers( type );
221}
222
[0bd3faf]223void GenType::postvisit( ast::UnionInstType const * type ) {
[8941b6b]224        result = type->name + handleGeneric( type ) + " " + result;
225        if ( options.genC ) result = "union " + result;
226        handleQualifiers( type );
227}
228
[0bd3faf]229void GenType::postvisit( ast::EnumInstType const * type ) {
[8941b6b]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
[0bd3faf]241void GenType::postvisit( ast::TypeInstType const * type ) {
[8941b6b]242        assertf( !options.genC, "TypeInstType should not reach code generation." );
243        result = type->name + " " + result;
244        handleQualifiers( type );
245}
246
[0bd3faf]247void GenType::postvisit( ast::TupleType const * type ) {
[8941b6b]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
[0bd3faf]260void GenType::postvisit( ast::VarArgsType const * type ) {
[8941b6b]261        result = "__builtin_va_list " + result;
262        handleQualifiers( type );
263}
264
[0bd3faf]265void GenType::postvisit( ast::ZeroType const * type ) {
[8941b6b]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
[0bd3faf]271void GenType::postvisit( ast::OneType const * type ) {
[8941b6b]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
[0bd3faf]277void GenType::postvisit( ast::GlobalScopeType const * type ) {
[8941b6b]278        assertf( !options.genC, "GlobalScopeType should not reach code generation." );
279        handleQualifiers( type );
280}
281
[0bd3faf]282void GenType::postvisit( ast::TraitInstType const * type ) {
[8941b6b]283        assertf( !options.genC, "TraitInstType should not reach code generation." );
284        result = type->name + " " + result;
285        handleQualifiers( type );
286}
287
[0bd3faf]288void GenType::postvisit( ast::TypeofType const * type ) {
[8941b6b]289        std::ostringstream os;
290        os << "typeof(";
[116d7e2]291        ast::Pass<CodeGenerator>::read( type->expr.get(), os, options );
[8941b6b]292        os << ") " << result;
293        result = os.str();
294        handleQualifiers( type );
295}
296
[0bd3faf]297void GenType::postvisit( ast::VTableType const * type ) {
[8941b6b]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
[0bd3faf]305void GenType::postvisit( ast::QualifiedType const * type ) {
[8941b6b]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
[0bd3faf]313void GenType::handleQualifiers( ast::Type const * type ) {
[8941b6b]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
[0bd3faf]328std::string GenType::genParamList( const ast::vector<ast::Type> & range ) {
[8941b6b]329        auto cur = range.begin();
330        auto end = range.end();
331        if ( cur == end ) return "";
332        std::ostringstream oss;
[934fa0f]333        UniqueName param( "__param_" );
334        while ( true ) {
335                oss << genType( *cur++, options.genC ? param.newName() : "", options );
[8941b6b]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() ) {
[0bd3faf]347                ast::Pass<CodeGenerator> cg( os, options );
[8941b6b]348                cg.core.genAttributes( type->attributes );
349        }
350
[0bd3faf]351        return os.str() + ast::Pass<GenType>::read( type, base, options );
[8941b6b]352}
353
354std::string genTypeNoAttr( ast::Type const * type, const std::string & base, const Options & options ) {
[0bd3faf]355        return ast::Pass<GenType>::read( type, base, options );
[8941b6b]356}
357
[51b7345]358} // namespace CodeGen
[51587aa]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.