source: src/SymTab/GenImplicitCall.cpp@ b51b2a6

ast-experimental
Last change on this file since b51b2a6 was 8913de4, checked in by Andrew Beach <ajbeach@…>, 2 years ago

Update in autogen that should help with some resolver issues and invariant checks. Some related headers were cleaned up to reduce new code files including old ones.

  • Property mode set to 100644
File size: 7.8 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2018 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// GenImplicitCall.hpp --
8//
9// Author : Andrew Beach
10// Created On : Fri Apr 14 14:38:00 2023
11// Last Modified By : Andrew Beach
12// Last Modified On : Fri Apr 14 14:46:00 2023
13// Update Count : 0
14//
15
16#include "GenImplicitCall.hpp"
17
18#include "AST/Decl.hpp" // for ObjectDecl
19#include "AST/Expr.hpp" // for ConstantExpr, UntypedExpr,...
20#include "AST/Init.hpp" // for SingleInit
21#include "AST/Inspect.hpp" // for isUnnamedBitfield
22#include "AST/Stmt.hpp" // for ExprStmt
23#include "AST/Type.hpp" // for ArrayType, BasicType, ...
24#include "CodeGen/OperatorTable.h" // for isCtorDtor
25#include "Common/UniqueName.h" // for UniqueName
26
27namespace SymTab {
28
29namespace {
30
31template< typename OutIter >
32ast::ptr< ast::Stmt > genCall(
33 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
34 const CodeLocation & loc, const std::string & fname, OutIter && out,
35 const ast::Type * type, const ast::Type * addCast, LoopDirection forward = LoopForward );
36
37/// inserts into out a generated call expression to function fname with arguments dstParam and
38/// srcParam. Should only be called with non-array types.
39/// optionally returns a statement which must be inserted prior to the containing loop, if
40/// there is one
41template< typename OutIter >
42ast::ptr< ast::Stmt > genScalarCall(
43 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
44 const CodeLocation & loc, std::string fname, OutIter && out, const ast::Type * type,
45 const ast::Type * addCast = nullptr
46) {
47 bool isReferenceCtorDtor = false;
48 if ( dynamic_cast< const ast::ReferenceType * >( type ) && CodeGen::isCtorDtor( fname ) ) {
49 // reference constructors are essentially application of the rebind operator.
50 // apply & to both arguments, do not need a cast
51 fname = "?=?";
52 dstParam = new ast::AddressExpr( dstParam );
53 addCast = nullptr;
54 isReferenceCtorDtor = true;
55 }
56
57 // want to be able to generate assignment, ctor, and dtor generically, so fname is one of
58 // "?=?", "?{}", or "^?{}"
59 ast::UntypedExpr * fExpr = new ast::UntypedExpr( loc, new ast::NameExpr( loc, fname ) );
60
61 if ( addCast ) {
62 // cast to T& with qualifiers removed, so that qualified objects can be constructed and
63 // destructed with the same functions as non-qualified objects. Unfortunately, lvalue
64 // is considered a qualifier - for AddressExpr to resolve, its argument must have an
65 // lvalue-qualified type, so remove all qualifiers except lvalue.
66 // xxx -- old code actually removed lvalue too...
67 ast::ptr< ast::Type > guard = addCast; // prevent castType from mutating addCast
68 ast::ptr< ast::Type > castType = addCast;
69 ast::remove_qualifiers(
70 castType,
71 ast::CV::Const | ast::CV::Volatile | ast::CV::Restrict | ast::CV::Atomic );
72 dstParam = new ast::CastExpr{ dstParam, new ast::ReferenceType{ castType } };
73 }
74 fExpr->args.emplace_back( dstParam );
75
76 ast::ptr<ast::Stmt> listInit = srcParam.buildListInit( fExpr );
77
78 // fetch next set of arguments
79 ++srcParam;
80
81 // return if adding reference fails -- will happen on default ctor and dtor
82 if ( isReferenceCtorDtor && ! srcParam.addReference() ) return listInit;
83
84 std::vector< ast::ptr< ast::Expr > > args = *srcParam;
85 splice( fExpr->args, args );
86
87 *out++ = new ast::ExprStmt{ loc, fExpr };
88
89 srcParam.clearArrayIndices();
90
91 return listInit;
92}
93
94
95/// Store in out a loop which calls fname on each element of the array with srcParam and
96/// dstParam as arguments. If forward is true, loop goes from 0 to N-1, else N-1 to 0
97template< typename OutIter >
98void genArrayCall(
99 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
100 const CodeLocation & loc, const std::string & fname, OutIter && out,
101 const ast::ArrayType * array, const ast::Type * addCast = nullptr,
102 LoopDirection forward = LoopForward
103) {
104 static UniqueName indexName( "_index" );
105
106 // for a flexible array member nothing is done -- user must define own assignment
107 if ( ! array->dimension ) return;
108
109 if ( addCast ) {
110 // peel off array layer from cast
111 addCast = strict_dynamic_cast< const ast::ArrayType * >( addCast )->base;
112 }
113
114 ast::ptr< ast::Expr > begin, end;
115 std::string cmp, update;
116
117 if ( forward ) {
118 // generate: for ( int i = 0; i < N; ++i )
119 begin = ast::ConstantExpr::from_int( loc, 0 );
120 end = array->dimension;
121 cmp = "?<?";
122 update = "++?";
123 } else {
124 // generate: for ( int i = N-1; i >= 0; --i )
125 begin = ast::UntypedExpr::createCall( loc, "?-?",
126 { array->dimension, ast::ConstantExpr::from_int( loc, 1 ) } );
127 end = ast::ConstantExpr::from_int( loc, 0 );
128 cmp = "?>=?";
129 update = "--?";
130 }
131
132 ast::ptr< ast::DeclWithType > index = new ast::ObjectDecl(
133 loc, indexName.newName(), new ast::BasicType( ast::BasicType::SignedInt ),
134 new ast::SingleInit( loc, begin ) );
135 ast::ptr< ast::Expr > indexVar = new ast::VariableExpr( loc, index );
136
137 ast::ptr< ast::Expr > cond = ast::UntypedExpr::createCall(
138 loc, cmp, { indexVar, end } );
139
140 ast::ptr< ast::Expr > inc = ast::UntypedExpr::createCall(
141 loc, update, { indexVar } );
142
143 ast::ptr< ast::Expr > dstIndex = ast::UntypedExpr::createCall(
144 loc, "?[?]", { dstParam, indexVar } );
145
146 // srcParam must keep track of the array indices to build the source parameter and/or
147 // array list initializer
148 srcParam.addArrayIndex( indexVar, array->dimension );
149
150 // for stmt's body, eventually containing call
151 ast::CompoundStmt * body = new ast::CompoundStmt( loc );
152 ast::ptr< ast::Stmt > listInit = genCall(
153 srcParam, dstIndex, loc, fname, std::back_inserter( body->kids ), array->base, addCast,
154 forward );
155
156 // block containing the stmt and index variable
157 ast::CompoundStmt * block = new ast::CompoundStmt( loc );
158 block->push_back( new ast::DeclStmt( loc, index ) );
159 if ( listInit ) { block->push_back( listInit ); }
160 block->push_back( new ast::ForStmt( loc, {}, cond, inc, body ) );
161
162 *out++ = block;
163}
164
165template< typename OutIter >
166ast::ptr< ast::Stmt > genCall(
167 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
168 const CodeLocation & loc, const std::string & fname, OutIter && out,
169 const ast::Type * type, const ast::Type * addCast, LoopDirection forward
170) {
171 if ( auto at = dynamic_cast< const ast::ArrayType * >( type ) ) {
172 genArrayCall(
173 srcParam, dstParam, loc, fname, std::forward< OutIter >(out), at, addCast,
174 forward );
175 return {};
176 } else {
177 return genScalarCall(
178 srcParam, dstParam, loc, fname, std::forward< OutIter >( out ), type, addCast );
179 }
180}
181
182} // namespace
183
184ast::ptr< ast::Stmt > genImplicitCall(
185 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
186 const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * obj,
187 LoopDirection forward
188) {
189 // unnamed bit fields are not copied as they cannot be accessed
190 if ( isUnnamedBitfield( obj ) ) return {};
191
192 ast::ptr< ast::Type > addCast;
193 if ( (fname == "?{}" || fname == "^?{}") && ( ! obj || ( obj && ! obj->bitfieldWidth ) ) ) {
194 assert( dstParam->result );
195 addCast = dstParam->result;
196 }
197
198 std::vector< ast::ptr< ast::Stmt > > stmts;
199 genCall(
200 srcParam, dstParam, loc, fname, back_inserter( stmts ), obj->type, addCast, forward );
201
202 if ( stmts.empty() ) {
203 return {};
204 } else if ( stmts.size() == 1 ) {
205 const ast::Stmt * callStmt = stmts.front();
206 if ( addCast ) {
207 // implicitly generated ctor/dtor calls should be wrapped so that later passes are
208 // aware they were generated.
209 callStmt = new ast::ImplicitCtorDtorStmt( callStmt->location, callStmt );
210 }
211 return callStmt;
212 } else {
213 assert( false );
214 return {};
215 }
216}
217
218} // namespace SymTab
219
220// Local Variables: //
221// tab-width: 4 //
222// mode: c++ //
223// compile-command: "make install" //
224// End: //
225
226
Note: See TracBrowser for help on using the repository browser.