source: src/SymTab/GenImplicitCall.cpp @ 6b1c4f2

ast-experimental
Last change on this file since 6b1c4f2 was fb4dc28, checked in by Andrew Beach <ajbeach@…>, 19 months 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.