source: src/SymTab/Autogen.h@ e5ea867

ADT arm-eh ast-experimental cleanup-dtors enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since e5ea867 was c13e8dc8, checked in by Rob Schluntz <rschlunt@…>, 8 years ago

Merge branch 'master' into cleanup-dtors

  • Property mode set to 100644
File size: 9.9 KB
RevLine 
[972e6f7]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
[c0aa336]11// Last Modified By : Peter A. Buhr
[6b0b624]12// Last Modified On : Sat Jul 22 09:50:25 2017
13// Update Count : 15
[972e6f7]14//
15
[6b0b624]16#pragma once
[972e6f7]17
[30f9072]18#include <cassert> // for assert
[d180746]19#include <string> // for string
[30f9072]20
[1a5ad8c]21#include "CodeGen/OperatorTable.h"
[30f9072]22#include "Common/UniqueName.h" // for UniqueName
23#include "InitTweak/InitTweak.h" // for InitExpander
24#include "SynTree/Constant.h" // for Constant
[d180746]25#include "SynTree/Declaration.h" // for DeclarationWithType, ObjectDecl
26#include "SynTree/Expression.h" // for NameExpr, ConstantExpr, UntypedExpr...
[30f9072]27#include "SynTree/Type.h" // for Type, ArrayType, Type::Qualifiers
[972e6f7]28
[d180746]29class CompoundStmt;
30class Statement;
31
[972e6f7]32namespace SymTab {
[2be1023]33 /// Generates assignment operators, constructors, and destructor for aggregate types as required
34 void autogenerateRoutines( std::list< Declaration * > &translationUnit );
35
36 /// returns true if obj's name is the empty string and it has a bitfield width
37 bool isUnnamedBitfield( ObjectDecl * obj );
38
[5f98ce5]39 /// size_t type - set when size_t typedef is seen. Useful in a few places,
40 /// such as in determining array dimension type
41 extern Type * SizeType;
42
[4fbdfae0]43 /// intrinsic dereference operator for unqualified types - set when *? function is seen in FindSpecialDeclarations.
44 /// Useful for creating dereference ApplicationExprs without a full resolver pass.
45 extern FunctionDecl * dereferenceOperator;
46
[837ce06]47 /// generate the type of an assignment function for paramType.
48 /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic
49 FunctionType * genAssignType( Type * paramType, bool maybePolymorphic = true );
[8a6cf7e]50
[837ce06]51 /// generate the type of a default constructor or destructor for paramType.
52 /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic
53 FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic = true );
[8404321]54
[837ce06]55 /// generate the type of a copy constructor for paramType.
56 /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic
57 FunctionType * genCopyType( Type * paramType, bool maybePolymorphic = true );
[8404321]58
[2be1023]59 /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
60 template< typename OutputIterator >
[b95fe40]61 Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast = nullptr, bool forward = true );
[2be1023]62
63 /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types.
[f9cebb5]64 /// optionally returns a statement which must be inserted prior to the containing loop, if there is one
[2be1023]65 template< typename OutputIterator >
[b95fe40]66 Statement * genScalarCall( InitTweak::InitExpander & srcParam, Expression * dstParam, std::string fname, OutputIterator out, Type * type, Type * addCast = nullptr ) {
[1a5ad8c]67 bool isReferenceCtorDtor = false;
68 if ( dynamic_cast< ReferenceType * >( type ) && CodeGen::isCtorDtor( fname ) ) {
69 // reference constructors are essentially application of the rebind operator.
70 // apply & to both arguments, do not need a cast
71 fname = "?=?";
72 dstParam = new AddressExpr( dstParam );
[b95fe40]73 addCast = nullptr;
[1a5ad8c]74 isReferenceCtorDtor = true;
75 }
76
[49148d5]77 // want to be able to generate assignment, ctor, and dtor generically,
78 // so fname is either ?=?, ?{}, or ^?{}
[1a5ad8c]79 UntypedExpr * fExpr = new UntypedExpr( new NameExpr( fname ) );
[49148d5]80
81 if ( addCast ) {
82 // cast to T& with qualifiers removed, so that qualified objects can be constructed
83 // and destructed with the same functions as non-qualified objects.
84 // unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument
85 // must have an lvalue qualified type, so remove all qualifiers except lvalue. If we ever
86 // remove lvalue as a qualifier, this can change to
87 // type->get_qualifiers() = Type::Qualifiers();
[b95fe40]88 Type * castType = addCast->clone();
[49148d5]89 castType->get_qualifiers() -= Type::Qualifiers( Type::Lvalue | Type::Const | Type::Volatile | Type::Restrict | Type::Atomic );
90 // castType->set_lvalue( true ); // xxx - might not need this
91 dstParam = new CastExpr( dstParam, new ReferenceType( Type::Qualifiers(), castType ) );
92 }
[1a5ad8c]93 fExpr->args.push_back( dstParam );
[2be1023]94
[49148d5]95 Statement * listInit = srcParam.buildListInit( fExpr );
[39f84a4]96
[1a5ad8c]97 // fetch next set of arguments
98 ++srcParam;
99
100 // return if adding reference fails - will happen on default constructor and destructor
101 if ( isReferenceCtorDtor && ! srcParam.addReference() ) {
102 delete fExpr;
103 return listInit;
104 }
105
106 std::list< Expression * > args = *srcParam;
107 fExpr->args.splice( fExpr->args.end(), args );
[4d2434a]108
[ba3706f]109 *out++ = new ExprStmt( fExpr );
[4d2434a]110
[49148d5]111 srcParam.clearArrayIndices();
[f9cebb5]112
[49148d5]113 return listInit;
[2be1023]114 }
115
116 /// Store in out a loop which calls fname on each element of the array with srcParam and dstParam as arguments.
117 /// If forward is true, loop goes from 0 to N-1, else N-1 to 0
118 template< typename OutputIterator >
[b95fe40]119 void genArrayCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, Type * addCast = nullptr, bool forward = true ) {
[2be1023]120 static UniqueName indexName( "_index" );
121
122 // for a flexible array member nothing is done -- user must define own assignment
[b95fe40]123 if ( ! array->get_dimension() ) return;
124
125 if ( addCast ) {
126 // peel off array layer from cast
127 ArrayType * at = strict_dynamic_cast< ArrayType * >( addCast );
128 addCast = at->base;
129 }
[2be1023]130
131 Expression * begin, * end, * update, * cmp;
132 if ( forward ) {
[579263a]133 // generate: for ( int i = 0; i < N; ++i )
134 begin = new ConstantExpr( Constant::from_int( 0 ) );
[1a5ad8c]135 end = array->dimension->clone();
[2be1023]136 cmp = new NameExpr( "?<?" );
137 update = new NameExpr( "++?" );
138 } else {
139 // generate: for ( int i = N-1; i >= 0; --i )
140 begin = new UntypedExpr( new NameExpr( "?-?" ) );
[1a5ad8c]141 ((UntypedExpr*)begin)->args.push_back( array->dimension->clone() );
142 ((UntypedExpr*)begin)->args.push_back( new ConstantExpr( Constant::from_int( 1 ) ) );
[579263a]143 end = new ConstantExpr( Constant::from_int( 0 ) );
[2be1023]144 cmp = new NameExpr( "?>=?" );
145 update = new NameExpr( "--?" );
146 }
147
[e4d829b]148 ObjectDecl *index = new ObjectDecl( indexName.newName(), Type::StorageClasses(), LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), new SingleInit( begin ) );
[2be1023]149
150 UntypedExpr *cond = new UntypedExpr( cmp );
[1a5ad8c]151 cond->args.push_back( new VariableExpr( index ) );
152 cond->args.push_back( end );
[2be1023]153
154 UntypedExpr *inc = new UntypedExpr( update );
[1a5ad8c]155 inc->args.push_back( new VariableExpr( index ) );
[2be1023]156
157 UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
[1a5ad8c]158 dstIndex->args.push_back( dstParam );
159 dstIndex->args.push_back( new VariableExpr( index ) );
[2be1023]160 dstParam = dstIndex;
161
[39f84a4]162 // srcParam must keep track of the array indices to build the
163 // source parameter and/or array list initializer
[1a5ad8c]164 srcParam.addArrayIndex( new VariableExpr( index ), array->dimension->clone() );
[39f84a4]165
[2be1023]166 // for stmt's body, eventually containing call
[ba3706f]167 CompoundStmt * body = new CompoundStmt();
[1a5ad8c]168 Statement * listInit = genCall( srcParam, dstParam, fname, back_inserter( body->kids ), array->base, addCast, forward );
[2be1023]169
170 // block containing for stmt and index variable
171 std::list<Statement *> initList;
[ba3706f]172 CompoundStmt * block = new CompoundStmt();
173 block->push_back( new DeclStmt( index ) );
[f9cebb5]174 if ( listInit ) block->get_kids().push_back( listInit );
[ba3706f]175 block->push_back( new ForStmt( initList, cond, inc, body ) );
[2be1023]176
177 *out++ = block;
178 }
179
180 template< typename OutputIterator >
[b95fe40]181 Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast, bool forward ) {
[2be1023]182 if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
[4d2434a]183 genArrayCall( srcParam, dstParam, fname, out, at, addCast, forward );
[f9cebb5]184 return 0;
[2be1023]185 } else {
[f9cebb5]186 return genScalarCall( srcParam, dstParam, fname, out, type, addCast );
[2be1023]187 }
188 }
189
190 /// inserts into out a generated call expression to function fname with arguments dstParam
191 /// and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. decl is the
192 /// object being constructed. The function wraps constructor and destructor calls in an
193 /// ImplicitCtorDtorStmt node.
194 template< typename OutputIterator >
[1a5ad8c]195 void genImplicitCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) {
[2be1023]196 ObjectDecl *obj = dynamic_cast<ObjectDecl *>( decl );
197 assert( obj );
198 // unnamed bit fields are not copied as they cannot be accessed
199 if ( isUnnamedBitfield( obj ) ) return;
200
[b95fe40]201 Type * addCast = nullptr;
202 if ( (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && ! obj->get_bitfieldWidth() ) ) ) {
203 assert( dstParam->result );
204 addCast = dstParam->result;
205 }
[2be1023]206 std::list< Statement * > stmts;
[1a5ad8c]207 genCall( srcParam, dstParam, fname, back_inserter( stmts ), obj->type, addCast, forward );
[2be1023]208
[6cf27a07]209 // 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
210 assert( stmts.size() <= 1 );
[f9cebb5]211 if ( stmts.size() == 1 ) {
212 Statement * callStmt = stmts.front();
213 if ( addCast ) {
214 // implicitly generated ctor/dtor calls should be wrapped
215 // so that later passes are aware they were generated.
216 // xxx - don't mark as an implicit ctor/dtor if obj is a bitfield,
217 // because this causes the address to be taken at codegen, which is illegal in C.
218 callStmt = new ImplicitCtorDtorStmt( callStmt );
219 }
220 *out++ = callStmt;
221 }
[2be1023]222 }
[972e6f7]223} // namespace SymTab
[6b0b624]224
225// Local Variables: //
226// tab-width: 4 //
227// mode: c++ //
228// compile-command: "make install" //
229// End: //
230
Note: See TracBrowser for help on using the repository browser.