source: src/SymTab/Autogen.h @ 30f9072

aaron-thesisarm-ehcleanup-dtorsdeferred_resndemanglerenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newwith_gc
Last change on this file since 30f9072 was 30f9072, checked in by Thierry Delisle <tdelisle@…>, 6 years ago

More cleanup on the headers

  • Property mode set to 100644
File size: 8.6 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// Autogen.h --
8//
9// Author           : Rob Schluntz
10// Created On       : Sun May 17 21:53:34 2015
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Wed Jun 21 17:25:26 2017
13// Update Count     : 14
14//
15
16#ifndef AUTOGEN_H
17#define AUTOGEN_H
18
19#include <cassert>                // for assert
20#include <iterator>               // for back_insert_iterator, back_inserter
21#include <list>                   // for list
22#include <string>                 // for string, operator==
23
24#include "Common/UniqueName.h"    // for UniqueName
25#include "InitTweak/InitTweak.h"  // for InitExpander
26#include "Parser/LinkageSpec.h"   // for C
27#include "SynTree/Constant.h"     // for Constant
28#include "SynTree/Declaration.h"  // for ObjectDecl, Declaration (ptr only)
29#include "SynTree/Expression.h"   // for UntypedExpr, NameExpr, VariableExpr
30#include "SynTree/Initializer.h"  // for SingleInit
31#include "SynTree/Label.h"        // for Label, noLabels
32#include "SynTree/Statement.h"    // for Statement (ptr only), CompoundStmt
33#include "SynTree/Type.h"         // for Type, ArrayType, Type::Qualifiers
34
35namespace SymTab {
36        /// Generates assignment operators, constructors, and destructor for aggregate types as required
37        void autogenerateRoutines( std::list< Declaration * > &translationUnit );
38
39        /// returns true if obj's name is the empty string and it has a bitfield width
40        bool isUnnamedBitfield( ObjectDecl * obj );
41
42        /// size_t type - set when size_t typedef is seen. Useful in a few places,
43        /// such as in determining array dimension type
44        extern Type * SizeType;
45
46        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
47        template< typename OutputIterator >
48        Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false, bool forward = true );
49
50        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types.
51        /// optionally returns a statement which must be inserted prior to the containing loop, if there is one
52        template< typename OutputIterator >
53        Statement * genScalarCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false ) {
54        // want to be able to generate assignment, ctor, and dtor generically,
55        // so fname is either ?=?, ?{}, or ^?{}
56        UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );
57
58        // do something special for unnamed members
59        dstParam = new AddressExpr( dstParam );
60        if ( addCast ) {
61                // cast to T* with qualifiers removed, so that qualified objects can be constructed
62                // and destructed with the same functions as non-qualified objects.
63                // unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument
64                // must have an lvalue qualified type, so remove all qualifiers except lvalue. If we ever
65                // remove lvalue as a qualifier, this can change to
66                //   type->get_qualifiers() = Type::Qualifiers();
67                assert( type );
68                Type * castType = type->clone();
69                castType->get_qualifiers() -= Type::Qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Atomic );
70                castType->set_lvalue( true ); // xxx - might not need this
71                dstParam = new CastExpr( dstParam, new PointerType( Type::Qualifiers(), castType ) );
72        }
73        fExpr->get_args().push_back( dstParam );
74
75        Statement * listInit = srcParam.buildListInit( fExpr );
76
77        std::list< Expression * > args = *++srcParam;
78        fExpr->get_args().splice( fExpr->get_args().end(), args );
79
80        *out++ = new ExprStmt( noLabels, fExpr );
81
82        srcParam.clearArrayIndices();
83
84        return listInit;
85        }
86
87        /// Store in out a loop which calls fname on each element of the array with srcParam and dstParam as arguments.
88        /// If forward is true, loop goes from 0 to N-1, else N-1 to 0
89        template< typename OutputIterator >
90        void genArrayCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, bool addCast = false, bool forward = true ) {
91                static UniqueName indexName( "_index" );
92
93                // for a flexible array member nothing is done -- user must define own assignment
94                if ( ! array->get_dimension() ) return ;
95
96                Expression * begin, * end, * update, * cmp;
97                if ( forward ) {
98                        // generate: for ( int i = 0; i < N; ++i )
99                        begin = new ConstantExpr( Constant::from_int( 0 ) );
100                        end = array->get_dimension()->clone();
101                        cmp = new NameExpr( "?<?" );
102                        update = new NameExpr( "++?" );
103                } else {
104                        // generate: for ( int i = N-1; i >= 0; --i )
105                        begin = new UntypedExpr( new NameExpr( "?-?" ) );
106                        ((UntypedExpr*)begin)->get_args().push_back( array->get_dimension()->clone() );
107                        ((UntypedExpr*)begin)->get_args().push_back( new ConstantExpr( Constant::from_int( 1 ) ) );
108                        end = new ConstantExpr( Constant::from_int( 0 ) );
109                        cmp = new NameExpr( "?>=?" );
110                        update = new NameExpr( "--?" );
111                }
112
113                ObjectDecl *index = new ObjectDecl( indexName.newName(), Type::StorageClasses(), LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), new SingleInit( begin ) );
114
115                UntypedExpr *cond = new UntypedExpr( cmp );
116                cond->get_args().push_back( new VariableExpr( index ) );
117                cond->get_args().push_back( end );
118
119                UntypedExpr *inc = new UntypedExpr( update );
120                inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
121
122                UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
123                dstIndex->get_args().push_back( dstParam );
124                dstIndex->get_args().push_back( new VariableExpr( index ) );
125                dstParam = dstIndex;
126
127                // srcParam must keep track of the array indices to build the
128                // source parameter and/or array list initializer
129                srcParam.addArrayIndex( new VariableExpr( index ), array->get_dimension()->clone() );
130
131                // for stmt's body, eventually containing call
132                CompoundStmt * body = new CompoundStmt( noLabels );
133                Statement * listInit = genCall( srcParam, dstParam, fname, back_inserter( body->get_kids() ), array->get_base(), addCast, forward );
134
135                // block containing for stmt and index variable
136                std::list<Statement *> initList;
137                CompoundStmt * block = new CompoundStmt( noLabels );
138                block->get_kids().push_back( new DeclStmt( noLabels, index ) );
139                if ( listInit ) block->get_kids().push_back( listInit );
140                block->get_kids().push_back( new ForStmt( noLabels, initList, cond, inc, body ) );
141
142                *out++ = block;
143        }
144
145        template< typename OutputIterator >
146        Statement * genCall( InitTweak::InitExpander &  srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast, bool forward ) {
147                if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
148                        genArrayCall( srcParam, dstParam, fname, out, at, addCast, forward );
149                        return 0;
150                } else {
151                        return genScalarCall( srcParam, dstParam, fname, out, type, addCast );
152                }
153        }
154
155        /// inserts into out a generated call expression to function fname with arguments dstParam
156        /// and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. decl is the
157        /// object being constructed. The function wraps constructor and destructor calls in an
158        /// ImplicitCtorDtorStmt node.
159        template< typename OutputIterator >
160        void genImplicitCall( InitTweak::InitExpander &  srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) {
161                ObjectDecl *obj = dynamic_cast<ObjectDecl *>( decl );
162                assert( obj );
163                // unnamed bit fields are not copied as they cannot be accessed
164                if ( isUnnamedBitfield( obj ) ) return;
165
166                bool addCast = (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && ! obj->get_bitfieldWidth() ) );
167                std::list< Statement * > stmts;
168                genCall( srcParam, dstParam, fname, back_inserter( stmts ), obj->get_type(), addCast, forward );
169
170                // currently genCall should produce at most one element, but if that changes then the next line needs to be updated to grab the statement which contains the call
171                assert( stmts.size() <= 1 );
172                if ( stmts.size() == 1 ) {
173                        Statement * callStmt = stmts.front();
174                        if ( addCast ) {
175                                // implicitly generated ctor/dtor calls should be wrapped
176                                // so that later passes are aware they were generated.
177                                // xxx - don't mark as an implicit ctor/dtor if obj is a bitfield,
178                                // because this causes the address to be taken at codegen, which is illegal in C.
179                                callStmt = new ImplicitCtorDtorStmt( callStmt );
180                        }
181                        *out++ = callStmt;
182                }
183        }
184} // namespace SymTab
185#endif // AUTOGEN_H
Note: See TracBrowser for help on using the repository browser.