source: src/SymTab/GenImplicitCall.cpp@ fece3d9

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

Moved new ast code out of one of the old files. The new file may have to change if SymTab is removed entirely, but for now at least, there is a lot less template code in headers.

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